// ChildFrm.cpp : implementation of the CChildFrame class
//
#include "stdafx.h"
#include "ImageLab.h"
#include "stdlib.h"
#include "ChildFrm.h"
#include "CrossNet.h"
#include "MainFrm.h"
#include <string>
#include <iostream>
#include "Output.h"
#include "FigureText.h"
#include "TermInput.h"
#include "ImageRetrieval.h"
#include "CrossModal.h"
#include "ImageData.h"

using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

static UINT indicators[] =
{
	ID_SEPARATOR,           // status line indicator
	ID_PIXEL_INFO,
};

// CChildFrame

IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)

BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
	ON_COMMAND(ID_FILE_CLOSE, &CChildFrame::OnFileClose)
	ON_COMMAND(ID_TEST, &CChildFrame::OnTest)
	ON_COMMAND(ID_FILE_IMAGEOPEN, &CChildFrame::OnImageOpen)
	ON_COMMAND(ID_OPR_MEDFILTER, &CChildFrame::OnMedianFilter)
	ON_COMMAND(ID_FILE_SAVE, &CChildFrame::OnImageSave)
	ON_COMMAND(ID_OPR_SEG_TH_OTSU2D, &CChildFrame::OnOtsu2d)
	ON_COMMAND(ID_OPR_SEG_TH_OTSU1D, &CChildFrame::OnOtsu1d)
	ON_COMMAND(ID_OPR_SEG_TH_GRAPHIC, &CChildFrame::OnGraphic)
	ON_COMMAND(ID_IMAGE_FOLDER_PROCESS, &CChildFrame::OnProcessFolder)
	ON_COMMAND(ID_IMAGE_SOM, &CChildFrame::OnImageSom)
	ON_COMMAND(ID_IMAGE_LAW_FILTER, &CChildFrame::OnLawFilter)
	ON_COMMAND(ID_IMAGE_FEATURE_PIXEL, &CChildFrame::OnPixelFeature)
	ON_COMMAND(ID_IMAGE_FEATURE_ZERNIKE, &CChildFrame::OnZernikeMoment)
	ON_COMMAND(ID_IMAGE_REDCHANNEL, &CChildFrame::OnRedChannel)
	ON_COMMAND(ID_IMAGE_GREENCHANNEL, &OnGreenChannel)
	ON_COMMAND(ID_IMAGE_BLUECHANNEL, &CChildFrame::OnBlueChannel)
	ON_COMMAND(ID_IMAGE_GRAYCHANNEL, &CChildFrame::OnGrayChannel)
	ON_COMMAND(ID_IMAGE_RECOVER, &CChildFrame::OnRecover)
	ON_COMMAND(ID_TEXT_SETCORPUS, &CChildFrame::SetCorpus)
	ON_COMMAND(ID_TEXT_MATCHCOMPOUND, &CChildFrame::matchCompound)
	ON_COMMAND(ID_IMAGE_ANNOTATION, &CChildFrame::OnCrossModalDialog)
	ON_COMMAND(ID_TEXT_MERGEFILE, &CChildFrame::TextMerge)
	ON_COMMAND(ID_CAPREF_EXTRACTION, &CChildFrame::CapRefExtraction)
	ON_COMMAND(ID_TERM_IDOC, &CChildFrame::OnTFTimesIDF)
	ON_COMMAND(ID_TEXT_LINGUISTIC_FOLDER, &CChildFrame::GetFolderLinguistic)
	ON_COMMAND(ID_RANDOMDOUBLES, &CChildFrame::OnGenerateMatrix)
	ON_COMMAND(ID_DATABASE_LOADDATA, &CChildFrame::OnLoadDatabase)
	ON_COMMAND(ID_IMAGERETRIEVAL, &CChildFrame::OnImageRetrieval)
	ON_COMMAND(ID_LOADFULLTEXT, &CChildFrame::OnLoadFulltext)
	ON_COMMAND(ID_SAVETODATABASE, &CChildFrame::OnSaveCrossModal)
	ON_COMMAND(ID_LOADFROMDATABASE, &CChildFrame::OnLoadCrossModal)
	ON_COMMAND(ID_MANUALANNOTATION, &CChildFrame::ManualAnnotation)
	ON_COMMAND(ID_LINGUISTIC_WORDLIST, &CChildFrame::GetListOfWords)
	ON_COMMAND(ID_LINGUISTIC_COLLOCATIONS, &CChildFrame::Collocations)
	ON_COMMAND(ID_IMAGECLUSTERING, &CChildFrame::ImageClustering)
	ON_COMMAND(ID_BOOTSTRAPLEARNING_MULTISENSORY, &CChildFrame::BootstrappingMultimodal)
	ON_COMMAND(ID_BOOTSTRAPLEARNING_IMAGES, &CChildFrame::BootstrappingImages)
	ON_COMMAND(ID_COMPANY_HSOM, &CChildFrame::ClusteringCompany)
	ON_WM_SETFOCUS()
	ON_WM_CREATE()
	ON_UPDATE_COMMAND_UI(ID_PIXEL_INFO, CChildFrame::OnUpdatePane)
END_MESSAGE_MAP()


// CChildFrame construction/destruction

CChildFrame::CChildFrame()
{
	m_ImageRetrieval = NULL;
	m_ManualAnnotation = NULL;
	imageclustering = NULL;
	crossmodaldialog = NULL;
	is_corpus_set = 0;
	// TODO: add member initialization code here
}

CChildFrame::~CChildFrame()
{
	m_wndView.Destroy();
	SendMessage(WM_CLOSE);
}


BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying the CREATESTRUCT cs
	if( !CMDIChildWnd::PreCreateWindow(cs) )
		return FALSE;

	cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
	cs.lpszClass = AfxRegisterWndClass(0);
	return TRUE;
}


// CChildFrame diagnostics

#ifdef _DEBUG
void CChildFrame::AssertValid() const
{
	CMDIChildWnd::AssertValid();
}

void CChildFrame::Dump(CDumpContext& dc) const
{
	CMDIChildWnd::Dump(dc);
}

#endif //_DEBUG


// CChildFrame message handlers
void CChildFrame::OnFileClose() 
{
	// To close the frame, just send a WM_CLOSE, which is the equivalent
	// choosing close from the system menu.
	m_wndView.Destroy();
	SendMessage(WM_CLOSE);
}

int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	CRect lpRect;
	CChildFrame::GetClientRect(&lpRect);
	// create a view to occupy the client area of the frame
	if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, 
		lpRect, this, AFX_IDW_PANE_FIRST, NULL))
	{
		TRACE0("Failed to create view window\n");
		return -1;
	}

	if(!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("Failed to create statusbar\n");
		return -1;
	}
	m_wndView.OnNewImage();

	CChildFrame::SetTitle(m_wndView.getImageName());
	CChildFrame::UpdateFrameTitleForDocument(CString(""));
	m_CrossNet = NULL;
	return 0;
}


void CChildFrame::OnSetFocus(CWnd* pOldWnd) 
{
	CMDIChildWnd::OnSetFocus(pOldWnd);

	m_wndView.SetFocus();
}

BOOL CChildFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 
{
	// let the view have first crack at the command
	if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;
	
	// otherwise, do default handling
	return CMDIChildWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

//a test function
void CChildFrame::OnTest(void)
{
	m_wndView.OnTest();
	return;
//	CChildFrame::GetListOfWords();
//	m_wndView.OnWaveletTransform();
//read the training and testing data
	//define dialog class
/*	HRESULT hResult;
	CString strFilter;
	//file selection filter
	strFilter = "Text File (*.txt)|*.txt||";
	//initialize the dialog
	CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
//image training data set
	CString dlgTitle = CString("Training image dataset");
	dlg.m_ofn.lpstrTitle = dlgTitle;
	//display the dialog for selecting files
	hResult = (int)dlg.DoModal();
	if(FAILED(hResult))
	{
		::AfxMessageBox(CString("Failed to Open Dialog"), MB_OK, 0);
		return;
	}
	//open the file for image training
	CFile cfile;
	CFileException e;
	//if no file is selected
	if(dlg.GetFileName()=="")
	{
		::AfxMessageBox(CString("No file is selected"), MB_OK, 0);
		return;
	}
	//if failed to open the file display the error message
	if(!cfile.Open(dlg.GetFileName(), CFile::modeRead, &e))
	{
		WCHAR errorMsg[1024];
		e.GetErrorMessage(errorMsg, 1024, 0);
		::AfxMessageBox(CString("Failed to open the text file:\r\n")+CString(errorMsg, 1024), MB_OK, 0);
		return;
	}
	//read the file to buffer
	int file_len = (int)cfile.GetLength();
	char* buffer = (char*)malloc(sizeof(char)*file_len);
	UINT nByteRead = cfile.Read(buffer, (int)cfile.GetLength());
	cfile.Close();
	//get the dimension of the input file
	int m_c;
	int m_r;
	if(!CChildFrame::GetDataDimension(buffer, file_len, &m_c, &m_r))
	{
		::AfxMessageBox(CString("Failed to get data dimension"), MB_OK, 0);
		return;
	}
	//read the data
	double** m_data = (double**)malloc(sizeof(double*)*m_r);
	for(int i=0; i<m_r; i++)
		m_data[i] = (double*)malloc(sizeof(double)*m_c);
	if(!CChildFrame::ReadMatrixData(buffer, file_len, m_c, m_r, m_data))
	{
		::AfxMessageBox(CString("Failed to read the data"), MB_OK, 0);
		return;
	}
	//free memory
	free(buffer);
	int** a_matrix = (int**)malloc(sizeof(int)*16);
	for(int i=0; i<16; i++)
		a_matrix[i] = (int*)calloc(16, sizeof(int));
	for(int i=0; i<m_r; i++)
		a_matrix[(int)m_data[i][0]][(int)m_data[i][1]] ++;
	CString str;
	for(int i=0; i<16; i++)
	{
		for(int j=0; j<16; j++)
		{
			str += bf.douTostr(a_matrix[i][j]);
			str += "\t";
		}
		str += "\r\n";
	}
	CString strindex;
	for(int i=0; i<16; i++)
	{
		for(int j=0; j<16; j++)
		{
			for(int k=0; k<m_r; k++)
			{
				if((int)m_data[k][0]==i && (int)m_data[k][1]==j)
				{
					char* t = bf.IntToChar(k);
					strindex += CString(t, (int)log10((double)k)+1);
					strindex += ";";
				}
			}
			strindex += "\t";
		}
		strindex += "\r\n";
	}
	bf.stringToFile(str, CString("Save the Result Matrix as ..."));
	bf.stringToFile(strindex, CString("Save the Index Result Matrix as ..."));
	return;
/*	CFile corpusFile;
	CFileException e;
	CString strFilter("Text file|*.txt");
	HRESULT hResult;

	CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
//	dlg.m_ofn.lpstrFilter = strFilter;
	hResult = (int)dlg.DoModal();

	corpusFile.Open(dlg.GetFileName(), CFile::modeRead, &e);
	char* buffer = (char*)malloc(sizeof(char)*(int)corpusFile.GetLength());
	UINT nByteRead = corpusFile.Read(buffer, (int)corpusFile.GetLength());
//get the words
	int number = CChildFrame::getWordCount(buffer, (int)corpusFile.GetLength());
	int* wordnum = (int*)malloc(sizeof(int)*number);
	char** words = (char**)malloc(sizeof(char*)*number);
	for(int i=0; i<number; i++)
	{
		words[i] = (char*)malloc(sizeof(char)*100);
	}
	bool get_word = CChildFrame::readWords(buffer, (int)corpusFile.GetLength(), words, wordnum, number);
	int* h_index = (int*)malloc(sizeof(int)*number);
	for(int i=0; i<number; i++)
	{
		h_index[i] = atoi(words[i]);
	}
	CString str;
	for(int i=0; i<number; i++)
	{
		str += douTostr(h_index[i]);
		str += "\t";
	}
	::AfxMessageBox(douTostr(number), MB_OK, 0);
	::AfxMessageBox(str, MB_OK, 0);
	m_wndView.PlotBinary(h_index, number);
*/
}

//open an new image;
void CChildFrame::OnImageOpen(void)
{
	m_wndView.OnFileOpenimage();
	CChildFrame::SetTitle(m_wndView.getImageName());
	CChildFrame::UpdateFrameTitleForDocument(CString(""));
	return;
}

//save the image
void CChildFrame::OnImageSave(void)
{
	m_wndView.OnFileSaveImage();
	return;
}

//2d otsu segmentation
void CChildFrame::OnOtsu2d(void)
{
	m_wndView.Otsu2d();
	return;
}

//1d otsu segmentation
void CChildFrame::OnOtsu1d(void)
{
	m_wndView.Otsu1d();
	return;
}

//median filter
void CChildFrame::OnMedianFilter(void)
{
	m_wndView.MedianFilter();
	return;
}

//Law's filter
void CChildFrame::OnLawFilter(void)
{
	m_wndView.OnLawFilter();
	return;
}

//process a folder of images
void CChildFrame::OnProcessFolder(void)
{
	m_wndView.BatchImage();
//define folder object
	return;
}

//image segmentation using SOM
void CChildFrame::OnImageSom(void)
{
	m_wndView.OnImageSelfOrg();
	return;
}

//extract pixel features
void CChildFrame::OnPixelFeature(void)
{
	m_wndView.pixelFeature();
	return;
}

//extract Zernike Moment
void CChildFrame::OnZernikeMoment(void)
{
	int z_n = 5;
	int z_m = 5;
	double** zernike = 	m_wndView.getZernikeImage(z_n, z_m);
	CString str;
	for(int i=0; i<m_wndView.getZernikeNum(z_n, z_m)*3; i++)
	{
		str += douTostr(sqrt(zernike[i][0]*zernike[i][0]+zernike[i][1]*zernike[i][1]));
		str += "\t";
	}
	CChildFrame::stringToFile(str);
	return;
}

//display red channel
void CChildFrame::OnRedChannel(void)
{
	m_wndView.OnRedChannel();
	return;
}

//display green channel
void CChildFrame::OnGreenChannel(void)
{
	m_wndView.OnGreenChannel();
	return;
}

//display blue channel
void CChildFrame::OnBlueChannel(void)
{
	m_wndView.OnBlueChannel();
	return;
}

//display gray image
void CChildFrame::OnGrayChannel(void)
{
	m_wndView.OnGrayChannel();
	return;
}

//recover image
void CChildFrame::OnRecover(void)
{
	m_wndView.OnRecover();
	return;
}

void CChildFrame::SetCorpus(void)
{
	CFile corpusFile;
	CFileException e;
	CString strFilter("Text file (*.txt)|*.txt");
	HRESULT hResult;

	CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
//	dlg.m_ofn.lpstrFilter = strFilter;
	hResult = (int)dlg.DoModal();
	if(!hResult)
	{
		::AfxMessageBox(CString("failed to open the dialog"), MB_OK, 0);
		throw string("failed to open the dialog");
		return;
	}
	if(!dlg.GetFileName().IsEmpty())
	{
		if(!corpusFile.Open(dlg.GetFileName(), CFile::modeRead, &e))
		{
			WCHAR ErrorMsg[1024];
			e.GetErrorMessage(ErrorMsg, 1024, 0);
			::AfxMessageBox(CString(ErrorMsg, 1024), MB_OK, 0);
			return;
		}
	}
//not finished yet
	else
	{
		::AfxMessageBox(CString("No file selected!"), MB_OK, 0);
		throw string("No file is selected");
		return;
	}
//open the file and read it to buffer
	if(is_corpus_set)
	{
		CChildFrame::DestroyCorpus();
	}
	char* buffer = (char*)malloc(sizeof(char)*(int)corpusFile.GetLength());
	UINT nByteRead = corpusFile.Read(buffer, (int)corpusFile.GetLength());
//get the words
	int corpus_num = CChildFrame::getWordCount(buffer, (int)corpusFile.GetLength());
	corpus_word_num = (int*)malloc(sizeof(int)*corpus_num);
	word_compound = (char**)malloc(sizeof(char*)*corpus_num);
	for(int i=0; i<corpus_num; i++)
	{
		word_compound[i] = (char*)malloc(sizeof(char)*255);
	}
	bool get_word = CChildFrame::readWords(buffer, (int)corpusFile.GetLength(), word_compound, corpus_word_num, corpus_num);
//test if words obtained	
	if(get_word==0)
	{
		::AfxMessageBox(CString("no words found"), MB_OK, 0);
		throw string("No words found");
		return;
	}
//index compound
	compound_total = CChildFrame::getCompoundNum(buffer, (int)corpusFile.GetLength());
	compound_index = (int*)calloc(compound_total, sizeof(int));
	compound_num = (int*)calloc(compound_total, sizeof(int));
	compound_frequency = (int*)calloc(compound_total, sizeof(int));
//set the compound index;
	bool c_flag = CChildFrame::getCompoundIndex(buffer, (int)corpusFile.GetLength(), compound_index, compound_num);
//close the file and free the memory
	if(c_flag==0)
	{
		::AfxMessageBox(CString("failed to get compound index"), MB_OK, 0);
		throw string("Failed to get compound index");
		return;
	}
	corpusFile.Close();
	free(buffer);
//read the frequency of compounds
	//!!!!!important!!!!!! reduce the compound_num by 1, which contain the frequency
	for(int i=0; i<compound_total; i++)
	{
		compound_frequency[i] = atoi(word_compound[compound_index[i]+compound_num[i]-1]);
		compound_num[i] --;
	}
//construct the division of compounds
	//number of divisions
	COutput outdata;
	outdata.m_string = CString("Give the Number of Divisions");
	outdata.m_data1 = 16;
	outdata.DoModal();
	num_division = (int)outdata.m_data1;
//calculate the distribution of each division
	double division_frequency = (log((double)compound_frequency[0])-log((double)
		compound_frequency[compound_total-1])+0.00000000001)/num_division;
//number of compounds in each division
	division_num = (int*)calloc(num_division, sizeof(int));
	int cur_division = 0;
	//determine the compound ID
	compound_id = (int*)malloc(sizeof(int)*compound_total);
	for(int i=0; i<compound_total; i++)
	{
		//calculate the current compound sequency in the division
		compound_id[i] = (int)((log((double)compound_frequency[i])-log((double)
			compound_frequency[compound_total-1]))/division_frequency);
		division_num[compound_id[i]] ++;
	}
	//output results
	CString str = bf.douTostr(compound_total);
	str += " compound words are read\r\n";
	::AfxMessageBox(str, MB_OK, 0);
//free memory
	//change indicator
	is_corpus_set = 1;
	return;
}

//function for compound matched
void CChildFrame::matchCompound(void)
{
	if(!is_corpus_set)
	{
		::AfxMessageBox(CString("No corpus set"), MB_OK, 0);
		return;
	}
	CString strFilter("Text file|*.txt");
	HRESULT hResult;
	CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
	//open a window for selecting file
	hResult = (int)dlg.DoModal();
	if(FAILED(hResult))
	{
		::AfxMessageBox(CString("failed to open file"), MB_OK, 0);
		return;
	}
	::AfxMessageBox(dlg.GetFileName(), MB_OK, 0);
	CString compound_str = CChildFrame::getCompound(dlg.GetFileName());
	::AfxMessageBox(compound_str, MB_OK, 0);
	return;
}

//get linguistic feature
double* CChildFrame::getLinguisticFeature(CString filename)
{
//validate if corpus is set or not
	if(!is_corpus_set)
	{
		double* err = new double;
		*err = -1;
		::AfxMessageBox(CString("No corpus set"), MB_OK, 0);
		return err;
	}
//open the file
	CFile text_file;
	CFileException e;
	//read the file selected
	if(!text_file.Open(filename, CFile::modeRead, &e))
	{
		TCHAR szError[1024];
		e.GetErrorMessage(szError, 1024);
		::AfxMessageBox((CString("failed to open file")+CString(szError)), MB_OK, 0);
		double* err = new double;
		*err = -1;
		return err;
	}
	//read the file into buffer
	char* buffer = (char*)malloc(sizeof(char)*(int)text_file.GetLength());
	UINT nByteRead = text_file.Read(buffer, (int)text_file.GetLength());
	//get the number of words
	int c_num = CChildFrame::getWordCount(buffer, (int)text_file.GetLength());
	//locate memory and read the words
	char** c_words = (char**)malloc(sizeof(char*)*c_num);
	int* w_num = (int*)malloc(sizeof(int)*c_num);
	for(int i=0; i<c_num; i++)
	{
		c_words[i] = (char*)malloc(sizeof(char)*100);
	}
	bool r_flag = CChildFrame::readWords(buffer, (int)text_file.GetLength(), c_words, w_num, c_num);
	//if fail to read words
	if(!r_flag)
	{
		::AfxMessageBox(CString("no words read"), MB_OK, 0);
		double* err = new double;
		*err = -1;
		return err;
	}
	//close the file and the buffer
	text_file.Close();
	free(buffer);
//start matching compound words and get linguistic features
	//determine the compound matched
	bool* compound_exist = (bool*)calloc(compound_total, sizeof(bool));
	for(int i=0; i<c_num; i++)
	{
		for(int j=0; j<compound_total; j++)
		{
			int count = 0;
			bool flag = 1;
			while(flag && count<compound_num[j])
			{
				if(i+count<c_num)
				{
					if(w_num[i+count]==corpus_word_num[compound_index[j]+count])
					{
						flag = CChildFrame::matchChar(c_words[i+count], 
							word_compound[compound_index[j]+count], w_num[i+count]);
					}
					else
					{
						flag = false;
					}
				}
				else
				{
					flag = false;
				}
				count ++;
			}
			if(flag)
			{
				compound_exist[j] = 1;
			}
		}
	}
	//feature constructor
	double* l_feature = (double*)malloc(sizeof(double)*num_division);
	int* sum_div = (int*)calloc(num_division, sizeof(int));
	for(int i=0; i<compound_total; i++)
	{
		if(compound_exist[i])
		{
			sum_div[compound_id[i]] ++;
		}
	}
	for(int i=0; i<num_division; i++)
	{
		if(division_num[i]!=0)
			l_feature[i] = (double)sum_div[i] / (double)division_num[i];
		else
			l_feature[i] = 0;
	}
	//free up memory
	free(w_num);
	free(compound_exist);
	for(int i=0; i<c_num; i++)
	{
		free(c_words[i]);
	}
	free(sum_div);
	//return the feature
	return l_feature;
}
//matching compounds
CString CChildFrame::getCompound(CString filename)
{
//read text file
	//define file object
	CFile text_file;
	CFileException e;

	//read the file selected
	if(!text_file.Open(filename, CFile::modeRead, &e))
	{
		TCHAR szError[1024];
		e.GetErrorMessage(szError, 1024);
		::AfxMessageBox((CString("failed to open file")), MB_OK, 0);
		return CString("failed to open file\n")+CString(szError);
	}
	char* buffer = (char*)malloc(sizeof(char)*(int)text_file.GetLength());
	UINT nByteRead = text_file.Read(buffer, (int)text_file.GetLength());
	//get the number of words
	int c_num = CChildFrame::getWordCount(buffer, (int)text_file.GetLength());
	//locate memory and read the words
	char** c_words = (char**)malloc(sizeof(char*)*c_num);
	int* w_num = (int*)malloc(sizeof(char*)*c_num);
	for(int i=0; i<c_num; i++)
	{
		c_words[i] = (char*)malloc(sizeof(char)*100);
	}
	bool r_flag = CChildFrame::readWords(buffer, (int)text_file.GetLength(), c_words, w_num, c_num);
	if(!r_flag)
	{
		::AfxMessageBox(CString("no words read"), MB_OK, 0);
		return CString("no words read");
	}
	text_file.Close();
	free(buffer);
	::AfxMessageBox(douTostr(c_num), MB_OK, 0);
//start matching compound words
	int num_matched = 0;
	bool* compound_exist = (bool*)calloc(compound_total, sizeof(bool));
	for(int i=0; i<c_num; i++)
	{
		for(int j=0; j<compound_total; j++)
		{
			int count = 0;
			bool flag = 1;
			while(flag && count<compound_num[j])
			{
				if(i+count<c_num)
				{
					if(w_num[i+count]==corpus_word_num[compound_index[j]+count])
					{
						flag = CChildFrame::matchChar(c_words[i+count], 
							word_compound[compound_index[j]+count], w_num[i+count]);
					}
					else
					{
						flag = false;
					}
				}
				else
				{
					flag = false;
				}
				count ++;
			}
			if(flag)
			{
				num_matched ++;
			}
		}
	}
	::AfxMessageBox(CString("number of matched compounds: ")+douTostr(num_matched), MB_OK, 0);
	int* index_matched = (int*)malloc(sizeof(int)*num_matched);

	int current_matched = 0;

	for(int i=0; i<c_num; i++)
	{
		for(int j=0; j<compound_total; j++)
		{
			int count = 0;
			bool flag = 1;
			while(flag && count<compound_num[j])
			{
				if(i+count<c_num)
				{
					if(w_num[i+count]==corpus_word_num[compound_index[j]+count])
					{
						flag = CChildFrame::matchChar(c_words[i+count], 
							word_compound[compound_index[j]+count], w_num[i+count]);
					}
					else
					{
						flag = false;
					}
				}
				else
				{
					flag = false;
				}
				count ++;
			}
			if(flag)
			{
				index_matched[current_matched] = j;
				current_matched ++;
			}
		}
	}
	CString match_str;
	if(num_matched==0)
	{
		match_str += "No. compound matched";
		return match_str;
	}
	for(int i=0; i<num_matched; i++)
	{
		for(int j=0; j<compound_num[index_matched[i]]; j++)
		{
			match_str += CString(word_compound[compound_index[index_matched[i]]+j], 
				corpus_word_num[compound_index[index_matched[i]]+j]);
			match_str += " ";
		}
		match_str += "\r\n";
	}
	//free up memory
	free(w_num);
	for(int i=0; i<c_num; i++)
	{
		free(c_words[i]);
	}
	//return the mached compounds
	return match_str;
}

//matching keyrwords
void CChildFrame::matchKeywords(void/*CString* incomeKeywords, CString* matchedKeywords*/)
{
//define the cfile object
	CFile refFile;
	CFile keyFile;
	CFileException e1, e2;
	CString strFilter;
	strFilter = "Text file|*.txt";
	HRESULT hResult;

	CFileDialog dlg1(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
	CFileDialog dlg2(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);

	dlg1.m_ofn.lpstrFilter = strFilter;
	dlg2.m_ofn.lpstrFilter = strFilter;

//open the corpus file and read the words

	hResult = (int)dlg1.DoModal();
	if(FAILED(hResult)) 
	{
		CString str("Failed to open the file!");
		::AfxMessageBox(str, MB_OK, 0);
		return;
	}
//read the file
	refFile.Open(dlg1.GetFileName(), CFile::modeRead, &e1);
	char* buffer = (char*)malloc(sizeof(char)*(int)refFile.GetLength());
	UINT nByteRead = refFile.Read(buffer, (int)refFile.GetLength());
//get the number of words
	int corpNum = CChildFrame::getWordCount(buffer, (int)refFile.GetLength());
//get the keywords
	char** corpWords = (char**)malloc(sizeof(char*)*corpNum);
	for(int i=0; i<corpNum; i++)
	{
		corpWords[i] = (char*)malloc(sizeof(char)*100);
	}
	int* corpChar = (int*)malloc(sizeof(int)*corpNum);
	bool corpR = CChildFrame::readWords(buffer, (int)refFile.GetLength(), corpWords, corpChar, corpNum);
	free(buffer);
	refFile.Close();
//open the figure caption files
	hResult = (int)dlg2.DoModal();
	if(FAILED(hResult))
	{
		CString str;
		str = "Failed to open the file!";
		::AfxMessageBox(str, MB_OK, 0);
		return;
	}
	keyFile.Open(dlg2.GetFileName(), CFile::modeRead, &e2);
//read the file get the number of words
	char* keybuffer = (char*)malloc(sizeof(char)*(int)keyFile.GetLength());
	nByteRead = keyFile.Read(keybuffer, (int)keyFile.GetLength());
	int keyNum = CChildFrame::getWordCount(keybuffer, (int)keyFile.GetLength());
//get the words
	char** keyWords = (char**)malloc(sizeof(char*)*keyNum);
	for(int i=0; i<keyNum; i++)
	{
		keyWords[i] = (char*)malloc(sizeof(char)*100);
	}
	int* keyChar = (int*)malloc(sizeof(int)*keyNum);
	bool keyR = CChildFrame::readWords(keybuffer, (int)keyFile.GetLength(), keyWords, keyChar, keyNum);
	free(keybuffer);
	keyFile.Close();
//match the keywords
	CPtrArray matchedWords;
	for(int i=0; i<keyNum; i++)
	{
		bool flag = 1;
		int j=0;
		while(flag&&(j<corpNum))
		{
			if(keyChar[i] == corpChar[j])
			{
				if(matchChar(keyWords[i], corpWords[j], keyChar[i]))
				{
					flag = 0;
					char* chartemp = (char*)malloc(sizeof(char)*100);
					for(int k=0; k<keyChar[i]; k++)
					{
						chartemp[k] = keyWords[i][k];
					}
					matchedWords.Add(chartemp);
				}
			}
			j++;
		}
	}
	int* matchedChar = (int*)malloc(matchedWords.GetCount()*sizeof(int));
	for(int i=0; i<matchedWords.GetCount(); i++)
	{
		char* chartemp = (char*)matchedWords.GetAt(i);
		int j=0;
		while(isLetter(chartemp[j]))
		{
			j++;
		}
		matchedChar[i] = j;
	}
	CString str;
	for(int i=0; i<corpNum; i++)
	{
		str += CString(corpWords[i], corpChar[i]);
		str += " ";
	}
	str += "\n";
	for(int i=0; i<keyNum; i++)
	{
		str += CString(keyWords[i], keyChar[i]);
		str += " ";
	}
	str += "\n";
	for(int i=0; i<matchedWords.GetCount(); i++)
	{
		char* chartemp = (char*)matchedWords.GetAt(i);
		str += CString(chartemp, matchedChar[i]);
		str += " ";
	}
	::AfxMessageBox(str, MB_OK, 0);
	return;
}

//is letter or not
bool CChildFrame::isLetter(char c)
{
	if((c<='z'&&c>='a')||(c<='Z'&&c>='A')||(c<='9'&&c>='0'))
		return 1;
	else
		return 0;
}

//count words from file
int CChildFrame::getWordCount(char* wfile, int flength)
{
	if(flength == 0)
	{
		::AfxMessageBox(CString("no words in file"), MB_OK, 0);
		return 0;
	}

	int NumWords = 0;
	if(isLetter(wfile[0]))
	{
		NumWords ++;
	}
	for(int i=1; i<flength; i++)
	{
		if(isLetter(wfile[i])&&(!isLetter(wfile[i-1])))
		{
			NumWords ++;
		}
	}
	return NumWords;
}

//count the number of compounds in the documents
int CChildFrame::getCompoundNum(char *wfile, int flength)
{
	if(flength == 0)
	{
		::AfxMessageBox(CString("file is empty"), MB_OK, 0);
		return 0;
	}
	int NumCompound = 0;
	//search for a stop of each compound
	for(int i=1; i<flength; i++)
	{
		if(wfile[i]==';')
		{
			NumCompound ++;
		}
	}
	return NumCompound;
}

//get the compound word index
bool CChildFrame::getCompoundIndex(char *wfile, int flength, int* c_index, int* c_num)
{
	//validattion
	if(flength == 0)
	{
		::AfxMessageBox(CString("file is empty"), MB_OK, 0);
		return 0;
	}
	if(!compound_total)
	{
		::AfxMessageBox(CString("no compound words"), MB_OK, 0);
		return 0;
	}
	//initialize numbers
	int currentCompound = 0;
	int currentWord = 0;
	int numWords = 0;
	//search the first word
	if(isLetter(wfile[0]))
	{
		numWords ++;
		currentWord ++;
	}
	//get the index and number of words in each compound
	for(int i=1; i<flength; i++)
	{
		//if found one that is not a word, increase the number of words in the compound by 1
		if(isLetter(wfile[i])&&(!isLetter(wfile[i-1])))
		{
			numWords ++;
			currentWord ++;
		}
		//if found a ;, move the compound index to the next one
		if(wfile[i]==';')
		{
			c_num[currentCompound] = numWords;
			if(currentCompound<compound_total-1)
			{
				c_index[++currentCompound] = currentWord;
			}
			numWords = 0;
		}
	}
	return 1;
}

//read words from the buffer
bool CChildFrame::readWords(char* wfile, int flength, char** words, int* numChar, int NumWords)
{
	if(NumWords==0)
	{
		::AfxMessageBox(CString("no words"), MB_OK, 0);
		return 0;
	}
	int currentWord = 0;
//read the words
	//get the first word
	int count = 0;
	if(isLetter(wfile[0]))
	{
		words[0][0] = wfile[0];
		count ++;
		bool flag = 1;
		while(flag)
		{
			if(count>flength-1)
			{
				flag = 0;
			}
			if(flag)
			{
				if(isLetter(wfile[count]))
				{
					words[0][count] = wfile[count];
					count++;
				}
				else
				{
					flag = 0;
				}
			}
		}
		currentWord ++;
		numChar[0] = count;
	}
	//get the rest of the words
	int i=1;
	while(i<flength)
	{
		if(isLetter(wfile[i])&&(!isLetter(wfile[i-1])))
		{
			words[currentWord][0] = wfile[i];
			bool flag = 1;
			int tempcount = 1;
			while(flag)
			{
				i++;
				if(i>flength-1)
				{
					flag = 0;
				}
				if(flag)
				{
					if(isLetter(wfile[i]))
					{
						words[currentWord][tempcount++] = wfile[i];
					}
					else
					{
						flag = 0;
					}
				}
			}
			numChar[currentWord] = tempcount;
			currentWord++;
		}
		i++;
	}
	return 1;
}

//match two chars
bool CChildFrame::matchChar(char* char1, char* char2, int charL)
{
	bool flag = 1;
	for(int i=0; i<charL; i++)
	{
		//if captical letter
		if(char1[i]>='A'&&char1[i]<='Z')
		{
			if(char1[i]!=char2[i]&&(char1[i]+32)!=char2[i])
				flag = 0;
		}
		else
		{
			if(char1[i]>='a'&&char1[i]<='z')
			{
				if(char1[i]!=char2[i]&&(char1[i]-32)!=char2[i])
					flag = 0;
			}
			else
			{
				if(char1[i]!=char2[i])
					flag = 0;
			}
		}
	}
	return flag;
}

//convert double to string
CString CChildFrame::douTostr( double dou )
{
	int decimal , sign, i;
	char *buffer = new char [10];
	char *buffer1 = new char [10] ;
	int precision = 10;
	int err;

	err = _ecvt_s( buffer, _CVTBUFSIZE, dou , precision , &decimal , & sign ) ;

	if ( decimal == 0 )
	{
		buffer1[0] = '0' ;
		buffer1[1] = '.' ;
		for ( int i = 2 ; i < 10 ; i ++ )
		{
			buffer1[i] = buffer[i-2] ;
		}
	}
	if ( decimal > 0 )
	{
		for ( i = 0 ; i < decimal ; i ++ )
		{
			buffer1[i] = buffer[i] ;
		}
		buffer1[i++] = '.' ;
		for ( ; i < 10 ; i ++ )
		{
			buffer1[i] = buffer[i-1] ;
		}
	}
	if ( decimal < 0 )
	{
		buffer1[0] = '0' ;
		buffer1[1] = '.' ;
		for ( i = 2 ; i < abs ( decimal ) + 2 ; i ++ )
		{
			buffer1[i] = '0' ;
		}
		int j = 0 ;
		for ( ; i < 10 ; i ++ )
		{
			buffer1[i] = buffer[j++] ;
		}
	}

	CString cstring ;

	if(dou<0)
		cstring = "-";
	for ( i = 0 ; i < 10 ; i ++ )
	{
		cstring = cstring + buffer1[i] ;
	}
	return cstring ;
}

//write a string to file
bool CChildFrame::stringToFile(CString str)
{
	CFile cfile;
	HRESULT hResult;
	CString strFilter;
	CSimpleArray<GUID> aguidFileTypes;
	CFileException e;
	strFilter = "text file (*.txt)|.txt";

	CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,strFilter);
	hResult = (int)dlg.DoModal();
	if (FAILED(hResult))
	{
		return 0;
	}
	CString strFileName;
	CString strExtension;

	strFileName = dlg.m_ofn.lpstrFile;
	cfile.Open(strFileName, CFile::modeRead|CFile::modeCreate|CFile::modeWrite, &e);
	cfile.Write(str, str.GetLength()*2);
	cfile.Close();
	return 1;
}

//destroy corpus
bool CChildFrame::DestroyCorpus(void)
{
	if(is_corpus_set)
	{
		for(int i=0; i<corpus_num; i++)
		{
			free(word_compound[i]);
		}
		free(corpus_word_num);
		free(compound_index);
		free(compound_num);
		free(compound_id);
		free(compound_frequency);
		free(division_num);
	}
	corpus_num = 0;
	is_corpus_set = 0;
	return 1;
}

//cross modal for image annotation
void CChildFrame::GetTrainingTesting(void)
{
//get the number of zernike moment
	int z_n = 5;
	int z_m = 5;
	int d_image = m_wndView.getZernikeNum(z_n, z_m)*3;
//determine if corpus set
	if(is_corpus_set!=1)
	{
		::AfxMessageBox(CString("Corpus not set!\nPlease select file for corpus"), MB_OK, 0);
		CChildFrame::SetCorpus();
	}
//define a folder view
	LPWSTR lpszDir = new WCHAR[_MAX_PATH];
	LPWSTR buffer = new WCHAR[_MAX_PATH];
	LPWSTR lpszDirT = new WCHAR[_MAX_PATH];
	LPWSTR bufferT = new WCHAR[_MAX_PATH];
	::OleInitialize(NULL);
	BROWSEINFO br_info;
	memset(&br_info, 0, sizeof(br_info));
	br_info.ulFlags = BIF_USENEWUI;
	br_info.hwndOwner = NULL;
	br_info.lpszTitle = _T("Please Select a Folder Containing Training Images");
	LPITEMIDLIST pidl;
	//browse for the training images
	pidl = ::SHBrowseForFolder(&br_info);
	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDir) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	else
	{
		::AfxMessageBox(CString("no folder selected!"), MB_OK, 0);
		return;
	}
	//browse for testing images
	pidl = ::SHBrowseForFolder(&br_info);
	br_info.lpszTitle = _T("Please Select a Folder Containing Training Images");
	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDirT) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	else
	{
		::AfxMessageBox(CString("no folder selected!"), MB_OK, 0);
		return;
	}
	::OleUninitialize();
	//find the file with .bmp
	CString findfile = lpszDir;
	findfile += "\\*.bmp";
	CFileFind finder;
	BOOL bWorking = finder.FindFile(findfile);
//get the number of images in the folder
	int num_image = 0;
	while (bWorking)
	{
		bWorking = finder.FindNextFile();
		num_image ++;
	}
	finder.Close();
//open images and load image features
	bWorking = finder.FindFile(findfile);
	//locate memory for zernike moment
	double** img_feature = (double**)malloc(sizeof(double*)*num_image);
	for(int i=0; i<num_image; i++)
	{
		img_feature[i] = (double*)malloc(sizeof(double)*d_image);
	}
	double** lgn_feature = (double**)malloc(sizeof(double*)*num_image);
//open the folder to get image features and linguistic features
	int count = 0;
	while (bWorking)
	{
		//find the next file and combine the path to be open
		bWorking = finder.FindNextFile();
		LPTSTR filename = ::PathCombine(buffer, lpszDir, finder.GetFileName());
		//open the image and get the zernike moment
		if(!m_wndView.OnImageOpen(CString(filename), finder.GetFileName()))
		{
			::AfxMessageBox(CString("Failed to Open Image:")+CString(filename), MB_OK, 0);
			return;
		}
		double** cur_feature = m_wndView.getZernikeImage(z_n, z_m);
		for(int i=0; i<d_image; i++)
		{
			img_feature[count][i] = sqrt(cur_feature[i][0]*cur_feature[i][0]+
				cur_feature[i][1]*cur_feature[i][1]);
		}
		//free up the memory storing zernike moment
		for(int i=0; i<d_image; i++)
		{
			free(cur_feature[i]);
		}
		//open the text file
		CString textfile = finder.GetFileName();
		textfile.Truncate((int)textfile.GetLength()-4);
		textfile += CString("_Caption.txt");
		LPTSTR textname = ::PathCombine(buffer, lpszDir, textfile);
		//and get the linguistic feature
		lgn_feature[count] = CChildFrame::getLinguisticFeature(CString(textname));
		count ++;
	}
	finder.Close();
	//select a folder containing the testing images
	//search images files in the testing folder and read it
	findfile = CString(lpszDirT);
	findfile += "\\*.bmp";
	bWorking = finder.FindFile(findfile);
	CString str;
	double* img_test = (double*)malloc(sizeof(double)*d_image);
	double* txt_test = (double*)malloc(sizeof(double)*num_division);
	while(bWorking)
	{
		//open the image file
		//get filename
		bWorking = finder.FindNextFile();
		LPTSTR imagename = ::PathCombine(bufferT, lpszDirT, finder.GetFileName());
		if(!m_wndView.OnImageOpen(CString(imagename), finder.GetFileName()))
		{
			::AfxMessageBox(CString("Failed to load image!"), MB_OK, 0);
			return;
		}
		//get the zernike moment of image
		double** test_f = m_wndView.getZernikeImage(z_n, z_m);
		for(int i=0; i<d_image; i++)
		{
			img_test[i] = sqrt(test_f[i][0]*test_f[i][0]+test_f[i][1]*test_f[i][1]);
		}
		//get the name of the testing text file
		CString textname = finder.GetFileName();
		textname.Truncate((int)textname.GetLength()-4);
		textname += CString("_Caption.txt");
		LPTSTR textfile = ::PathCombine(bufferT, lpszDirT, textname);
		//open the text file and get the linguistic feature
		txt_test = CChildFrame::getLinguisticFeature(CString(textfile));
	}
	finder.Close();	//set parameter for the cross net
//free memory
	free(img_test);
	free(txt_test);
	for(int i=0; i<num_image; i++)
	{
		free(img_feature[i]);
		free(lgn_feature[i]);
	}
	free(lpszDir);
	free(lpszDirT);
	free(buffer);
	return;
}

//graphic thresholding
void CChildFrame::OnGraphic(void)
{
	m_wndView.GraphicSOM();
	return;
}

//merge text from several files into a single file
void CChildFrame::TextMerge(void)
{
//define a folder class
	LPWSTR lpszDir = new WCHAR[_MAX_PATH];
	LPWSTR buffer = new WCHAR[_MAX_PATH];
	::OleInitialize(NULL);
	BROWSEINFO br_info;
	memset(&br_info, 0, sizeof(br_info));

	br_info.ulFlags = BIF_USENEWUI;
	br_info.hwndOwner = NULL;
	br_info.lpszTitle = _T("Please Select a Folder");

	LPITEMIDLIST pidl;
	pidl = ::SHBrowseForFolder(&br_info);

	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDir) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	
	::OleUninitialize();
	CString findfile = lpszDir;
	findfile += "\\*.txt";
	CFileFind finder;
	BOOL bWorking = finder.FindFile(findfile);
	CPtrArray fileStr;
//count the number of files
	int count = 0;
	while (bWorking)
	{
		bWorking = finder.FindNextFile();
		count ++;
	}
	finder.Close();
	long* filelength = (long*)malloc(sizeof(long)*count);
	count = 0;
//read the file content
	bWorking = finder.FindFile(findfile);
	while (bWorking)
	{
		bWorking = finder.FindNextFile();
		LPTSTR filename = ::PathCombine(buffer, lpszDir, finder.GetFileName());
		CFile txtfile;
		CFileException e;
		if(!txtfile.Open(filename, CFile::modeRead, &e))
		{
			TCHAR szError[1024];
			e.GetErrorMessage(szError, 1024);
			return;
		}
		char* filechar = (char*)malloc(sizeof(char)*(int)(txtfile.GetLength()));
		UINT uread = txtfile.Read(filechar, (int)txtfile.GetLength());
		filelength[count] = (long)txtfile.GetLength();
		txtfile.Close();
		fileStr.Add(filechar);
		count ++;
	}
//merge the files
	CString str;
	for(int i=0; i<count; i++)
	{
		str += CString((char*)fileStr.GetAt(i), filelength[i]);
		str += "\r\n";
	}
	bf.stringToFile(str, CString("merged file"));
	return;
}

//search backward for the beginning of the sentence
int CChildFrame::BackwardStop(int curpos, char* m_source, int m_slen)
{
	bool flag = 1;
	int dotpos = curpos ;
	int tappos = bf.SearchBackward('\t', m_source, curpos, m_slen);
	int eolpos = bf.SearchBackward('\n', m_source, curpos, m_slen);
	int entpos = bf.SearchBackward('\r', m_source, curpos, m_slen);
	while(flag)
	{
		//search the next dotpos;
		dotpos = bf.SearchBackward('.', m_source, dotpos, m_slen);
		//if dot is not found, end the loop and return the max of tappos, eolpos, and entpos;
		if(dotpos<0)
			return max(0, max(tappos, max(eolpos, entpos)));
		else	//if found
		{
			//check the position of the dot, if it is in front of any of the tappos, eolpos, 
			//or entpos, if yes, return the max of tappos, eolpos, and entpos;
			if(dotpos<tappos||dotpos<eolpos||dotpos<entpos)
				return max(0, max(tappos, max(eolpos, entpos)));
			else	//if not
			{
				//check if the pos is a full stop, if yes, end the loop and return it;
				if(bf.ValidateFullStop(dotpos, m_source, m_slen))
					return dotpos;
				//if not, go back to the loop to search for the next dotpos;
			}
		}
	}
	return max(0, dotpos);
}

//search forward for the end of the sentence
int CChildFrame::ForwardStop(int curpos, char* m_source, int m_slen)
{
	bool flag = 1;
	int dotpos = curpos;
	int tappos = bf.SearchForward('\t', m_source, curpos, m_slen);
	int eolpos = bf.SearchForward('\n', m_source, curpos, m_slen);
	int entpos = bf.SearchForward('\r', m_source, curpos, m_slen);
	while(flag)
	{
		//search for the next dotpos
		dotpos = bf.SearchForward('.', m_source, dotpos, m_slen);
		//if the dotpos is not found, end the loop return the min of tappos, eolpos, or entpos;
		if(dotpos>=m_slen)
			return min(m_slen, min(tappos, min(eolpos, entpos)));
		else	//if dotpos is found
		{
			//if the dotpos is larger than the tappos, eolpos, or entpos, return the min of them
			if(dotpos>tappos||dotpos>eolpos||dotpos>entpos)
				return min(m_slen, min(tappos, min(eolpos, entpos)));
			else	//if not
			{
				//validate if the dot is a full stop, if yes return it
				if(bf.ValidateFullStop(dotpos, m_source, m_slen))
					return dotpos;
				//if not, go back to the loop for the next dotpos
			}
		}
	}
	return min(m_slen, dotpos);
}

//extract the figure caption and references from paper content
void CChildFrame::CapRefExtraction(void)
{
	LPWSTR lpszDir = new WCHAR[_MAX_PATH];
	LPWSTR lpszDirT = new WCHAR[_MAX_PATH];
	LPWSTR buffer = new WCHAR[_MAX_PATH];
	::OleInitialize(NULL);
	BROWSEINFO br_info;
	memset(&br_info, 0, sizeof(br_info));
//browse the path for images
	br_info.ulFlags = BIF_USENEWUI;
	br_info.hwndOwner = NULL;
	br_info.lpszTitle = _T("Please Select a Folder for Images");

	LPITEMIDLIST pidl;
	pidl = ::SHBrowseForFolder(&br_info);

	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDir) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	::OleUninitialize();
//*end of browse for images
//*browse the folder for the full paper for the image
	::OleInitialize(NULL);
	memset(&br_info, 0, sizeof(br_info));

	br_info.ulFlags = BIF_USENEWUI;
	br_info.hwndOwner = NULL;
	br_info.lpszTitle = _T("Please Select a Folder for Papers");

	pidl = ::SHBrowseForFolder(&br_info);
	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDirT) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	::OleUninitialize();
//*end of browse for full paper
	CString findfile = lpszDir;
	CString fullpaper = lpszDirT;
	findfile += "\\*.bmp";
	CFileFind finder;
	BOOL bWorking = finder.FindFile(findfile);
	while (bWorking)
	{
		bWorking = finder.FindNextFile();
//create files and extract text for the Caption and References
		//get the image name;
		CString iname = finder.GetFileName();
		iname.Truncate((int)iname.GetLength()-4);
	//extract the figure number and search to open the full paper
		//extract the paper name
		char* imagename = bf.CStringToChar(iname);
		int pnamelen = bf.SearchBackward('_', imagename, (int)iname.GetLength()-1, (int)iname.GetLength());
		CString papername = CString(imagename, pnamelen);
		papername += ".txt";
		LPTSTR paperpath = ::PathCombine(buffer, lpszDirT, papername);
	//extract the figure sequence
		//check if the sequency > 10 ?
		int imageseq = 0;
		if(imagename[(int)iname.GetLength()-2]<'9'&&imagename[(int)iname.GetLength()-2]>='1')
		{
			imageseq = ((int)imagename[(int)iname.GetLength()-2]-(int)'0')*10; //convert char to int
		}
		imageseq += ((int)imagename[(int)iname.GetLength()-1]-(int)'0'); //convert char to int
		//open the paper file
		CFile paperfile;
		CFileException e;
		if(!paperfile.Open(paperpath, CFile::modeRead, &e)) //if fail to open the file
			//print the message to log file
		{
			TCHAR szError[256];
			e.GetErrorMessage(szError, 256);
			bf.WriteToLog(CString(szError));
		}
		else	//else extract the figure caption and references
		{
		//extract the figure caption
			//read the paper file into buffer
			char* papercon = (char*)malloc(sizeof(char)*(int)paperfile.GetLength());
			int paperlen = (int)paperfile.GetLength();
			UINT paperread = paperfile.Read(papercon, (UINT)paperlen);
			paperfile.Close();
		//detect the pattern of the Figure caption
			bool isFigdot = 1;
			bool isFigure = 1;
			bool isFig = 1;
			//try Fig.
			char* figindex = "Fig.";
			if(bf.SearchStr(figindex, papercon, 0, 4, paperlen)<(paperlen-4))
				isFigdot = 1;
			else
				isFigdot = 0;
			//try Figure
			figindex = "Figure ";
			if(bf.SearchStr(figindex, papercon, 0, 7, paperlen)<(paperlen-6))
				isFigure = 1;
			else
				isFigure = 0;
			//try Fig 
			figindex = "Fig ";
			if(bf.SearchStr(figindex, papercon, 0, 4, paperlen)<(paperlen-4))
				isFig = 1;
			else
				isFig = 0;
		//construct search string for figure caption and reference
			char* figcap = (char*)malloc(sizeof(char)*paperlen);
			int figcaplen = 0;
			char* figref = (char*)malloc(sizeof(char)*paperlen);
			int figreflen = 0;
			COutput outdata;
			char* figrefsearch = (char*)malloc(sizeof(char)*256);
			int searchreflen = 0;
			char* figrefpulsearch = (char*)malloc(sizeof(char)*256);
			int searchrefpullen = 0;
		//if Fig. is used
			if(isFigdot)
			{
			//construct figure index;
				figrefsearch[0] = 'F';
				figrefsearch[1] = 'i';
				figrefsearch[2] = 'g';
				figrefsearch[3] = '.';
				figrefsearch[4] = ' ';
				figrefpulsearch[0] = 'F';
				figrefpulsearch[1] = 'i';
				figrefpulsearch[2] = 'g';
				figrefpulsearch[3] = 's';
				figrefpulsearch[4] = '.';
				figrefpulsearch[5] = ' ';
				if(imageseq>=10)
				{
					searchreflen = 7;
					figrefsearch[5] = char((int)(imageseq/10))+'0';
					figrefsearch[6] = char((int)(imageseq%10))+'0';
					searchrefpullen = 8;
					figrefpulsearch[6] = char((int)(imageseq/10))+'0';
					figrefpulsearch[7] = char((int)(imageseq%10))+'0';
				}
				else
				{
					searchreflen = 6;
					figrefsearch[5] = char((int)imageseq)+'0';
					searchrefpullen = 7;
					figrefpulsearch[6] = char((int)imageseq)+'0';
				}
				CChildFrame::SearchCapRef(figrefsearch, searchreflen, papercon, paperlen, figcap,
					&figcaplen, figref, &figreflen);
				CChildFrame::SearchCapRef(figrefpulsearch, searchrefpullen, papercon, paperlen,
					figcap, &figcaplen, figref, &figreflen);
			}
		//is Figure is used
			if(isFigure)
			{
			//construct figure reference;
				figrefsearch[0] = 'F';
				figrefsearch[1] = 'i';
				figrefsearch[2] = 'g';
				figrefsearch[3] = 'u';
				figrefsearch[4] = 'r';
				figrefsearch[5] = 'e';
				figrefsearch[6] = ' ';
				figrefpulsearch[0] = 'F';
				figrefpulsearch[1] = 'i';
				figrefpulsearch[2] = 'g';
				figrefpulsearch[3] = 'u';
				figrefpulsearch[4] = 'r';
				figrefpulsearch[5] = 'e';
				figrefpulsearch[6] = 's';
				figrefpulsearch[7] = ' ';
				if(imageseq>=10)
				{
					figrefsearch[7] = char((int)(imageseq/10))+'0';
					figrefsearch[8] = char((int)(imageseq%10))+'0';
					searchreflen = 9;
					figrefpulsearch[8] = char((int)(imageseq/10))+'0';
					figrefpulsearch[9] = char((int)(imageseq%10))+'0';
					searchrefpullen = 10;
				}
				else
				{
					figrefsearch[7] = char((int)imageseq)+'0';
					searchreflen = 8;
					figrefpulsearch[8] = char((int)imageseq)+'0';
					searchrefpullen = 9;
				}
				CChildFrame::SearchCapRef(figrefsearch, searchreflen, papercon, paperlen, figcap,
					&figcaplen, figref, &figreflen);
				CChildFrame::SearchCapRef(figrefpulsearch, searchrefpullen, papercon, paperlen,
					figcap, &figcaplen, figref, &figreflen);
			}
		//if Fig  is used
			if(isFig)
			{
			//construct figure reference;
				figrefsearch[0] = 'F';
				figrefsearch[1] = 'i';
				figrefsearch[2] = 'g';
				figrefsearch[3] = ' ';
				figrefpulsearch[0] = 'F';
				figrefpulsearch[1] = 'i';
				figrefpulsearch[2] = 'g';
				figrefpulsearch[3] = 's';
				figrefpulsearch[4] = ' ';
				if(imageseq>=10)
				{
					figrefsearch[4] = char((int)(imageseq/10))+'0';
					figrefsearch[5] = char((int)(imageseq%10))+'0';
					searchreflen = 6;
					figrefpulsearch[5] = char((int)(imageseq/10))+'0';
					figrefpulsearch[6] = char((int)(imageseq%10))+'0';
					searchrefpullen = 7;
				}
				else
				{
					figrefsearch[4] = char((int)imageseq)+'0';
					searchreflen = 5;
					figrefpulsearch[5] = char((int)imageseq)+'0';
					searchrefpullen = 6;
				}
				CChildFrame::SearchCapRef(figrefsearch, searchreflen, papercon, paperlen, figcap,
					&figcaplen, figref, &figreflen);
				CChildFrame::SearchCapRef(figrefpulsearch, searchrefpullen, papercon, paperlen,
					figcap, &figcaplen, figref, &figreflen);
			}
		//if nothing is found. prompt user to validate
			if(figcaplen<10||figreflen<10)
			{
				char buf[5];
				CFigureText figuretext;
				figuretext.m_paper = CString(papercon, paperlen); //assign the paper content to the dialog
				_itoa_s(imageseq, buf, 5, 10);
				figuretext.m_FigCap = CString(buf, 2);
				figuretext.m_FigRef = figuretext.m_FigCap;
				figuretext.DoModal();
				free(figrefsearch);
				free(figrefpulsearch);
				figrefsearch = bf.CStringToChar(figuretext.m_FigCap);
				searchreflen = figuretext.m_FigCap.GetLength();
				figrefpulsearch = bf.CStringToChar(figuretext.m_FigRef);
				searchrefpullen = figuretext.m_FigRef.GetLength();
				CChildFrame::SearchCapRef(figrefsearch, searchreflen, papercon, paperlen, figcap,
					&figcaplen, figref, &figreflen);
				CChildFrame::SearchCapRef(figrefpulsearch, searchrefpullen, papercon, paperlen,
					figcap, &figcaplen, figref, &figreflen);
			}
			//return the input to search
			//save the caption to file
			CString capname = iname;
			capname += CString("_Caption.txt");
			LPTSTR cappath = ::PathCombine(buffer, lpszDir, capname);
			CFile capfile;
			if(!capfile.Open(cappath, CFile::modeCreate | CFile::modeWrite, &e))
			{
				CString strtemp("fail to create caption for:\r\n");
				strtemp += iname;
				::AfxMessageBox(strtemp, MB_OK, 0);
			}
			else
			{
				capfile.Write(figcap, figcaplen);
				free(figcap);
			}
			capfile.Close();
			//save the reference to file
			CString refname = iname + CString("_Reference.txt");
			LPTSTR refpath = ::PathCombine(buffer, lpszDir, refname);
			CFile reffile;
			if(!reffile.Open(refpath, CFile::modeCreate|CFile::modeWrite, &e))
			{
				CString strtemp("cannot create file for references:");
				strtemp += refname;
				::AfxMessageBox(strtemp, MB_OK, 0);
			}
			else
			{
				reffile.Write(figref, figreflen);
				reffile.Close();
				free(figref);
			}
		//end of save the references
			free(papercon);
			free(figrefsearch);
			free(figrefpulsearch);
	//end of open the file
		}
	}
	return;
}

//search the paper for the caption and reference using an index
void CChildFrame::SearchCapRef(char* m_index, int m_ilen, char* m_source, int m_slen, char* m_cap,
							   int* m_clen, char* m_ref, int* m_rlen)
{
	int figpos = 0;
	int figend = 0;
	int refpos;
	int refend;
	int i=0;
	while(i<m_slen)
	{
		i = bf.SearchStr(m_index, m_source, i, m_ilen, m_slen);
		//check if i is a validate location for caption or references
		if(i>=0 && i<(m_slen-m_ilen-5) && (m_source[i+m_ilen]<'0'||m_source[i+m_ilen]>'9'))
		{
		//check if there is content before, if yet, it is reference, if not, not reference
		//if the letter before is not end of line or enter, it is a reference
			if(m_source[max(0, i-1)]!='\n' && m_source[max(0, i-1)]!='\r')/*i<(paperlen-searchreflen-1)*/
			{
				//locate the whole sentences.
				refpos = CChildFrame::BackwardStop(i, m_source, m_slen);
				refend = CChildFrame::ForwardStop(i, m_source, m_slen);
				//push the sentence into the reference string
				for(int j=0; j<refend-refpos+1; j++)
				{
					m_ref[*m_rlen+j]=m_source[refpos+j+1];
				}
				*m_rlen += (refend-refpos+1);
				//move i to the end of sentence to jump over the ref inside the sentence
				i = refend;
			}
			else	//it is a caption
			{
				figpos = i;
				figend = bf.SearchForward('\r', m_source, figpos+m_ilen, m_slen);
				for(int j=0; j<figend-figpos; j++)
				{
					m_cap[*m_clen+j]=m_source[figpos+j];
				}
				*m_clen += (figend-figpos);
				i=figend;
			}
		}
	}
	return;
}

//search documents for terms frequency and inverse documents frequency
void CChildFrame::OnTFTimesIDF(void)
{
	LPWSTR lpszDir = new WCHAR[_MAX_PATH];
	LPWSTR lpszDirT = new WCHAR[_MAX_PATH];
	LPWSTR buffer = new WCHAR[_MAX_PATH];
	::OleInitialize(NULL);
	BROWSEINFO br_info;
	memset(&br_info, 0, sizeof(br_info));
//browse the path for documents
	br_info.ulFlags = BIF_USENEWUI;
	br_info.hwndOwner = NULL;
	br_info.lpszTitle = _T("Please Select a Folder for Documents");

	LPITEMIDLIST pidl;
	pidl = ::SHBrowseForFolder(&br_info);

	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDir) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	else
	{
		::AfxMessageBox(CString("No folder selected"), MB_OK, 0);
		return;
	}
	::OleUninitialize();
//*end of browse for documents
	//display the dialog for loading terms
	CTermInput terminput;
	terminput.DoModal();
//read the terms
	//convert the CString to char*
	char* cterms = bf.CStringToChar(terminput.m_terms);
	int termlen = terminput.m_terms.GetLength();
	terminput.m_terms.Empty();
//determine the number of terms
	int termnum = 0;
	//if the number of chars in cterms is less or equalled to 0, return;
	if(termlen<=0)
	{
		::AfxMessageBox(CString("no terms read"), MB_OK, 0);
		return;
	}
	//validate if end of line present at the end or not
	if(cterms[termlen-1]!='\n')
	{
		::AfxMessageBox(CString("Error!\r\nPlease Hit Enter after the Last Term"), MB_OK, 0);
		return;
	}
	//determine if the first char is letter, is yes, increase the number of terms by one
	if(CChildFrame::isLetter(cterms[0]))
	{
		termnum++;
	}
	//if end of line and the next char is a letter, increase the number of terms by 1
	for(int i=0; i<termlen; i++)
	{
		if(cterms[i]=='\n'&&(i+1)<termlen)
			if(CChildFrame::isLetter(cterms[i+1]))
				termnum++;
	}
//locate the beginning of every terms and specified the length of every terms
	int* begin_t = (int*)malloc(sizeof(int)*termnum);
	int* len_t = (int*)malloc(sizeof(int)*termnum);
	//the first term
	begin_t[0] = 0;
	//locate the other terms
	int count = 0;
	for(int i=0; i<termlen; i++)
	{
		if(cterms[i]=='\r') //if encounter an enter, return the length of the terms
			len_t[count]=i-begin_t[count];
		if(cterms[i]=='\n') //if it is the end of line, determine if it is the end or not
		{
			if(i<termlen-1) //if not end of document
			{
				if(CChildFrame::isLetter(cterms[i+1]))
				{
					count ++;
					begin_t[count] = i+1;
				}
			}
		}
	}
//search documents in the folder and count the number of documents
	CString findfile = lpszDir;
	CString fullpaper = lpszDirT;
	int count_d = 0;
	findfile += "\\*.txt";
	CFileFind finder;
	BOOL bWorking = finder.FindFile(findfile);
	CString str;
	while (bWorking)
	{
		count_d ++;
		bWorking = finder.FindNextFile();
	}
//create pointer for saving the document names
	char** DocumentName = (char**)malloc(sizeof(char*)*count_d);
//define the measurements for terms
	int** term_f = (int**)malloc(sizeof(int*)*termnum);	//terms frequency
	for(int i=0; i<termnum; i++)
	{
		term_f[i] = (int*)malloc(sizeof(int)*count_d);
	}
	//initialize the term frequency to -1 for knowing if the file is read or not
	for(int i=0; i<termnum; i++)
	{
		for(int j=0; j<count_d; j++)
		{
			term_f[i][j] = -1;
		}
	}
//search the documents in the folder
	bWorking = finder.FindFile(findfile);
	count_d = 0;
	while (bWorking)
	{
		bWorking = finder.FindNextFile();
	//get the path of the file and read it into buffer
		LPTSTR filename = ::PathCombine(buffer, lpszDir, finder.GetFileName());
		CFile cfile;
		CFileException e;
		//if file not open
		if(!cfile.Open(filename, CFile::modeRead, &e))
		{
			TCHAR errorMsg[1024];
			e.GetErrorMessage(errorMsg, 1024, 0);
			bf.WriteToLog(CString(errorMsg, 1024));
		}
		else
		{
			//read the file to buffer
			char* filechar = (char*)malloc(sizeof(char)*(int)cfile.GetLength());
			UINT uread = cfile.Read(filechar, (UINT)cfile.GetLength());
			int doc_l = (int)cfile.GetLength();
			cfile.Close();
			//search each term in the document and return the frequency
			for(int i=0; i<termnum; i++)
			{
				term_f[i][count_d] = 0;
				int j=0;
				while(j<doc_l)
				{
					//if a match is found, increase the frequency
					j=bf.SearchStr(&cterms[begin_t[i]], filechar, j, len_t[i], doc_l);
					if(j<doc_l-len_t[i]-1)
					{
						//if it is the first world found, validate if the one after the terms is
						//a legal letter or not, if not, a legal match is found
						if(j==0)
						{
							if(!CChildFrame::isLetter(filechar[j+len_t[i]]))
							{
								term_f[i][count_d]++;
							}
						}
						else	//if not first letter, validate if the ones before and after the term
								//is legal letter or not, if not, a legal match is found
						{
							if(!CChildFrame::isLetter(filechar[j-1])&&
								!CChildFrame::isLetter(filechar[j+len_t[i]]))
								term_f[i][count_d]++;
						}
					}
				}
			}
			//free the memory of filechar
			free(filechar);
		}
		DocumentName[count_d] = bf.CStringToChar(finder.GetFileName());
		count_d ++;
	}
	//determin the inverse document frequency and write to the string
	CString idocstr;
	double* idoc_f = (double*)malloc(sizeof(double)*termnum);
	for(int i=0; i<termnum; i++)
	{
		idocstr += CString(&cterms[begin_t[i]], len_t[i]);
		idocstr += "\t";
		idoc_f[i] = 0;
		for(int j=0; j<count_d; j++)
		{
			if(term_f[i][j]>0)
				idoc_f[i] ++;
		}
		if(idoc_f[i]!=0)
		{
			idoc_f[i] = log((double)count_d/(double)idoc_f[i])/log((double)2);
		}
		idocstr += bf.douTostr(idoc_f[i]);
		idocstr += "\r\n";
	}
	//calculate the TF*IDF
	double** tf_idf = (double**)malloc(sizeof(double*)*termnum);
	for(int i=0; i<termnum; i++)
	{
		tf_idf[i] = (double*)malloc(sizeof(double)*count_d);
		for(int j=0; j<count_d; j++)
		{
			tf_idf[i][j] = (double)term_f[i][j]*idoc_f[i];
		}
	}
//write the data of terms frequency and TFIDF to files for excel
//string for TF*IDF
	CString tfidfstr;
	for(int i=0; i<termnum/255+1; i++)
	{
		//write the header of the part of the table
		int j = 0;
		while(j<255&&(i*255+j)<termnum)
		{
			tfidfstr += CString(&cterms[begin_t[i*255+j]], len_t[i*255+j]);
			tfidfstr += CString("\t");
			j++;
		}
		tfidfstr += "\r\n";
		//write the part of the data to the table
		for(int k=0; k<count_d; k++)
		{
			j = 0;
			while(j<255&&(i*255+j)<termnum)
			{
				tfidfstr += bf.douTostr(tf_idf[i*255+j][k]);
				tfidfstr += "\t";
				j++;
			}
			tfidfstr += "\r\n";
		}
		tfidfstr += "\r\n";
	}
//string for terms frequency
	CString termfreqstr;
	for(int i=0; i<termnum/255+1; i++)
	{
		//write the header of the part of the table
		int j = 0;
		while(j<255&&(i*255+j<termnum))
		{
			termfreqstr += CString(&cterms[begin_t[i*255+j]], len_t[i*255+j]);
			termfreqstr += "\t";
			j++;
		}
		termfreqstr += "\r\n";
		//write the part of the data to the table
		for(int k=0; k<count_d; k++)
		{
			j = 0;
			while(j<255&&(i*255+j<termnum))
			{
				termfreqstr += bf.douTostr(term_f[i*255+j][k]);
				termfreqstr += "\t";
				j++;
			}
			termfreqstr += "\r\n";
		}
		termfreqstr += "\r\n";
	}

//select the terms that is large than a threshold of T into corpus
	//get a threshold manually
	COutput outdata;
	outdata.m_data1 = 10;
	outdata.m_string = CString("Please input a threshold for TF*IDF");
	outdata.DoModal();
	double T = outdata.m_data1;
	CString SelectedTerm;
	//scan the TFIDF to find the important terms
	for(int i=0; i<termnum; i++)
	{
	//detected if the max TFIDF is larger than the threshold or not
		bool selected = 0;
		for(int j=0; j<count_d; j++)
		{
			if(tf_idf[i][j]>T)
				selected = 1;
		}
		//if yes, insert to the selected terms
		if(selected)
		{
			SelectedTerm += CString(&cterms[begin_t[i]], len_t[i]);
			SelectedTerm += "\t";
			int termfreq = 0;
			for(int j=0; j<count_d; j++)
				termfreq += term_f[i][j];
			SelectedTerm += bf.douTostr(termfreq);
			SelectedTerm += "\t";
			double maxTfidf = 0;
			int maxTfidfIndex = 0;
			for(int j=0; j<count_d; j++)
				if(tf_idf[i][j]>maxTfidf)
				{
					maxTfidf = tf_idf[i][j];
					maxTfidfIndex = j;
				}
			SelectedTerm += bf.douTostr(maxTfidf);
			SelectedTerm += "\t";
			SelectedTerm += CString(DocumentName[maxTfidfIndex]);
			SelectedTerm += "\r\n";
		}
	}
	//write the frequency and inverse document frequency to file
	bf.stringToFile(termfreqstr, CString("Save the Frequency of Words as ..."));
	bf.stringToFile(idocstr, CString("Save the Inverse Document Frequency as ..."));
	bf.stringToFile(tfidfstr, CString("Save the TF*IDF as ..."));
	bf.stringToFile(SelectedTerm, CString("Save the Selected Terms as ..."));
	//free the memory
	free(cterms);
	free(begin_t);
	free(len_t);
	for(int i=0; i<termnum; i++)
	{
		free(term_f[i]);
		free(tf_idf[i]);
	}
	free(idoc_f);
	termfreqstr.Empty();
	idocstr.Empty();
	tfidfstr.Empty();
	return;
}

//perform the multinet training and testing for image annotation
void CChildFrame::ImageAnnotation(void)
{
//inform user about the data format
	::AfxMessageBox(CString("About to start\r\nPlease prepare the data file in the following format:\r\nNumColumns;NumRows;\r\nData11;Data12;...;\r\nData21;Data22;...;\r\n...;\r\nPress OK to Start"), MB_OK, 0);
//read the training and testing data
	//define dialog class
	HRESULT hResult;
	CString strFilter;
	//file selection filter
	strFilter = "Text File (*.txt)|*.txt||";
	//initialize the dialog
	CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
//image training data set
	CString dlgTitle = CString("Training image dataset");
	dlg.m_ofn.lpstrTitle = dlgTitle;
	//display the dialog for selecting files
	hResult = (int)dlg.DoModal();
	if(FAILED(hResult))
	{
		::AfxMessageBox(CString("Failed to Open Dialog"), MB_OK, 0);
		return;
	}
	//open the file for image training
	CFile cfile;
	CFileException e;
	//if no file is selected
	if(dlg.GetFileName()=="")
	{
		::AfxMessageBox(CString("No file is selected"), MB_OK, 0);
		return;
	}
	//if failed to open the file display the error message
	if(!cfile.Open(dlg.GetFileName(), CFile::modeRead, &e))
	{
		WCHAR errorMsg[1024];
		e.GetErrorMessage(errorMsg, 1024, 0);
		::AfxMessageBox(CString("Failed to open the text file:\r\n")+CString(errorMsg, 1024), MB_OK, 0);
		return;
	}
	//read the file to buffer
	int file_len = (int)cfile.GetLength();
	char* buffer = (char*)malloc(sizeof(char)*file_len);
	UINT nByteRead = cfile.Read(buffer, (int)cfile.GetLength());
	cfile.Close();
	//get the dimension of the input file
	int c_train_img;
	int r_train_img;
	if(!CChildFrame::GetDataDimension(buffer, file_len, &c_train_img, &r_train_img))
	{
		::AfxMessageBox(CString("Failed to get data dimension"), MB_OK, 0);
		return;
	}
	//read the data
	double** d_train_img = (double**)malloc(sizeof(double*)*r_train_img);
	for(int i=0; i<r_train_img; i++)
		d_train_img[i] = (double*)malloc(sizeof(double)*c_train_img);
	if(!CChildFrame::ReadMatrixData(buffer, file_len, c_train_img, r_train_img, d_train_img))
	{
		::AfxMessageBox(CString("Failed to read the data"), MB_OK, 0);
		return;
	}
	//free memory
	free(buffer);
//get the text training data set
	dlgTitle = CString("Training linguistic dataset");
	dlg.m_ofn.lpstrTitle = dlgTitle;
	//display the dialog for selecting files
	hResult = (int)dlg.DoModal();
	if(FAILED(hResult))
	{
		::AfxMessageBox(CString("Failed to Open Dialog"), MB_OK, 0);
		return;
	}
	//if no file is selected
	if(dlg.GetFileName()=="")
	{
		::AfxMessageBox(CString("No file is selected"), MB_OK, 0);
		return;
	}
	//if failed to open the file display the error message
	if(!cfile.Open(dlg.GetFileName(), CFile::modeRead, &e))
	{
		WCHAR errorMsg[1024];
		e.GetErrorMessage(errorMsg, 1024, 0);
		::AfxMessageBox(CString("Failed to open the text file:\r\n")+CString(errorMsg, 1024), MB_OK, 0);
		return;
	}
	//read the file to buffer
	file_len = (int)cfile.GetLength();
	buffer = (char*)malloc(sizeof(char)*file_len);
	nByteRead = cfile.Read(buffer, (int)cfile.GetLength());
	cfile.Close();
	//get the dimension of the input file
	int c_train_txt;
	int r_train_txt;
	if(!CChildFrame::GetDataDimension(buffer, file_len, &c_train_txt, &r_train_txt))
	{
		::AfxMessageBox(CString("Failed to get data dimension"), MB_OK, 0);
		return;
	}
	//read the data
	double** d_train_txt = (double**)malloc(sizeof(double*)*r_train_txt);
	for(int i=0; i<r_train_txt; i++)
		d_train_txt[i] = (double*)malloc(sizeof(double)*c_train_txt);
	if(!CChildFrame::ReadMatrixData(buffer, file_len, c_train_txt, r_train_txt, d_train_txt))
	{
		::AfxMessageBox(CString("Failed to read the data"), MB_OK, 0);
		return;
	}
	//free memory
	free(buffer);
//get the testing image data set
	dlgTitle = CString("Testing Image dataset");
	dlg.m_ofn.lpstrTitle = dlgTitle;
	hResult = (int)dlg.DoModal();
	if(FAILED(hResult))
	{
		::AfxMessageBox(CString("Failed to open the dialog!"), MB_OK, 0);
		return;
	}
	if(dlg.GetFileName()=="")
	{
		::AfxMessageBox(CString("No file is selected"), MB_OK, 0);
		return;
	}
	//open the file
	if(!cfile.Open(dlg.GetFileName(), CFile::modeRead, &e))
	{
		WCHAR errorMsg[1024];
		e.GetErrorMessage(errorMsg, 1024, 0);
		::AfxMessageBox(CString("Failed to open the text file:\r\n")+CString(errorMsg, 1024), MB_OK, 0);
		return;
	}
	//read the data
	file_len = (int)cfile.GetLength();
	buffer = (char*)malloc(sizeof(char)*file_len);
	nByteRead = cfile.Read(buffer, (UINT)cfile.GetLength());
	cfile.Close();
	//get the dimension of the dataset
	int c_test_img;
	int r_test_img;
	if(!CChildFrame::GetDataDimension(buffer, file_len, &c_test_img, &r_test_img))
	{
		::AfxMessageBox(CString("Failed to load dimension of the image testing data"), MB_OK, 0);
		return;
	}
	//read the data into the testing set
	double** d_test_img = (double**)malloc(sizeof(double*)*r_test_img);
	for(int i=0; i<r_test_img; i++)
		d_test_img[i] = (double*)malloc(sizeof(double)*c_test_img);
	if(!CChildFrame::ReadMatrixData(buffer, file_len, c_test_img, r_test_img, d_test_img))
	{
		::AfxMessageBox(CString("Failed to load the image testing data"), MB_OK, 0);
		return;
	}
	//free memory
	free(buffer);
//get the testing linguistic data set
	dlgTitle = CString("Testing linguistic dataset");
	dlg.m_ofn.lpstrTitle = dlgTitle;
	hResult = (int)dlg.DoModal();
	if(FAILED(hResult))
	{
		::AfxMessageBox(CString("Failed to open the dialog!"), MB_OK, 0);
		return;
	}
	if(dlg.GetFileName()=="")
	{
		::AfxMessageBox(CString("No file is selected"), MB_OK, 0);
		return;
	}
	//open the file
	if(!cfile.Open(dlg.GetFileName(), CFile::modeRead, &e))
	{
		WCHAR errorMsg[1024];
		e.GetErrorMessage(errorMsg, 1024, 0);
		::AfxMessageBox(CString("Failed to open the text file:\r\n")+CString(errorMsg, 1024), MB_OK, 0);
		return;
	}
	//read the data
	file_len = (int)cfile.GetLength();
	buffer = (char*)malloc(sizeof(char)*file_len);
	nByteRead = cfile.Read(buffer, (UINT)cfile.GetLength());
	cfile.Close();
	//get the dimension of the dataset
	int c_test_txt;
	int r_test_txt;
	if(!CChildFrame::GetDataDimension(buffer, file_len, &c_test_txt, &r_test_txt))
	{
		::AfxMessageBox(CString("Failed to load dimension of the linguistic testing data"), MB_OK, 0);
		return;
	}
	//read the data into the testing set
	double** d_test_txt = (double**)malloc(sizeof(double*)*r_test_txt);
	for(int i=0; i<r_test_txt; i++)
		d_test_txt[i] = (double*)malloc(sizeof(double)*c_test_txt);
	if(!CChildFrame::ReadMatrixData(buffer, file_len, c_test_txt, r_test_txt, d_test_txt))
	{
		::AfxMessageBox(CString("Failed to load the image testing data set"), MB_OK, 0);
		return;
	}
	//free memory
	free(buffer);
//end of load data
//validate the training and testing datasets
	if(r_train_img!=r_train_txt)
	{
		::AfxMessageBox(CString("Rows of training image and text set not equal!"), MB_OK, 0);
		return;
	}
	if(r_test_img!=r_test_txt)
	{
		::AfxMessageBox(CString("Rows of testing image and text set not equal!"), MB_OK, 0);
		return;
	}
	if(c_train_img!=c_test_img)
	{
		::AfxMessageBox(CString("Columns of training and testing image data set not equal!"), MB_OK, 0);
		return;
	}
	if(c_train_txt!=c_test_txt)
	{
		::AfxMessageBox(CString("Columns of training and testing image data set not equal!"), MB_OK, 0);
		return;
	}
//normalize the data
	//transpose the vector
	double** d_train_img_t = bf.matrixTransp(d_train_img, r_train_img, c_train_img);
	double** d_train_txt_t = bf.matrixTransp(d_train_txt, r_train_txt, c_train_txt);
	//normalize the vector
	double* ave_train_img = (double*)malloc(sizeof(double)*c_train_img);
	double* std_train_img = (double*)malloc(sizeof(double)*c_train_img);
	double* ave_train_txt = (double*)malloc(sizeof(double)*c_train_txt);
	double* std_train_txt = (double*)malloc(sizeof(double)*c_train_txt);
	if(!bf.normalizedData(d_train_img_t, r_train_img, c_train_img, ave_train_img, std_train_img))
	{
		::AfxMessageBox(CString("Failed to normalize image training set!"), MB_OK, 0);
		return;
	}
	if(!bf.normalizedData(d_train_txt_t, r_train_txt, c_train_txt, ave_train_txt, std_train_txt))
	{
		::AfxMessageBox(CString("Failed to normalize text training set!"), MB_OK, 0);
		return;
	}
//starting multi net training
	//define the parameters for the multi SOM
	COutput outdata;
	outdata.m_data1 = 8;
	outdata.m_data2 = 8;
	outdata.m_data3 = 8;
	outdata.m_data4 = 8;
	outdata.m_string = CString("Enter above the size of the map:\r\nSOM1Row\tSOM2Column\r\nSOM2Row\tSOM2Column\r\nPress OK to Continue");
	outdata.DoModal();

	int img_r = (int)outdata.m_data1;
	int img_c = (int)outdata.m_data2;
	int img_d = c_train_img;
	int txt_r = (int)outdata.m_data3;
	int txt_c = (int)outdata.m_data4;
	int txt_d = c_train_txt;
	int trainCycle = 1000;
	//define the cross net
	m_CrossNet = new CCrossNet(img_r, img_c, img_d, txt_r, txt_c, txt_d, trainCycle);
	m_CrossNet->NetIllustration(false);
	//train the network
	m_CrossNet->NetTraining(d_train_img_t, d_train_txt_t, r_train_img);
	//get the last round of winners
	int* winner1 = m_CrossNet->NetGetWinners1();
	int* winner2 = m_CrossNet->NetGetWinners2();
	//save the winners to file
	::AfxMessageBox(CString("Save the last round of winners to file"), MB_OK, 0);
	CString winner1str;
	CString winner2str;
	for(int i=0; i<r_train_img; i++)
	{
		winner1str += bf.douTostr(winner1[i]);
		winner1str += "\r\n";
		winner2str += bf.douTostr(winner2[i]);
		winner2str += "\r\n";
	}
	bf.stringToFile(winner1str, CString("Save the Winners of SOM 1 as ..."));
	bf.stringToFile(winner2str, CString("Save the Winners of SOM 2 as ..."));
//start the multinet testing
	//normalize the testing data
	::AfxMessageBox(CString("Finished traing!\r\nPress OK to start testing!"), MB_OK, 0);
	CString str;
/*	//testing the results based on the training set
	for(int i=0; i<r_train_txt; i++)
	{
		//normalize each vector according to the average and standard deviation
		for(int j=0; j<c_train_txt; j++)
			if(std_train_txt[j]!=0)
				d_train_txt[i][j] = (d_train_txt[i][j]-ave_train_txt[j])/std_train_txt[j];
		for(int j=0; j<c_train_img; j++)
			if(std_train_img[j]!=0)
				d_train_img[i][j] = (d_train_img[i][j]-ave_train_img[j])/std_train_img[j];
		//inseart the testing results into the string
		//annotation
		str += bf.douTostr(crossmodal.NetGet2(d_train_img[i]));
		str += CString("\t");
		str += bf.douTostr(crossmodal.NetGetSom2(d_train_txt[i]));
		str += CString("\t");
		//retrieval
		str += bf.douTostr(crossmodal.NetGetSom1(d_train_img[i]));
		str += CString("\t");
		str += bf.douTostr(crossmodal.NetGet1(d_train_txt[i]));
		str += CString("\r\n");
	}
*/	//loop to test each data;
	for(int i=0; i<r_test_txt; i++)
	{
		//normalize each vector according to the average and standard deviation
		for(int j=0; j<c_test_txt; j++)
			if(std_train_txt[j]!=0)
				d_test_txt[i][j] = (d_test_txt[i][j]-ave_train_txt[j])/std_train_txt[j];
		for(int j=0; j<c_test_img; j++)
			if(std_train_img[j]!=0)
				d_test_img[i][j] = (d_test_img[i][j]-ave_train_img[j])/std_train_img[j];
		//inseart the testing results into the string
		//annotation
		str += bf.douTostr(m_CrossNet->NetGet2(d_test_img[i]));
		str += CString("\t");
		str += bf.douTostr(m_CrossNet->NetGetSom2(d_test_txt[i]));
		str += CString("\t");
		//retrieval
		str += bf.douTostr(m_CrossNet->NetGetSom1(d_test_img[i]));
		str += CString("\t");
		str += bf.douTostr(m_CrossNet->NetGet1(d_test_txt[i]));
		str += CString("\r\n");
	}
	bf.stringToFile(str, CString("Save the Testing Results as ..."));
//free memory
	//free image feature memory
	for(int i=0; i<c_train_img; i++)
		free(d_train_img_t[i]);
	free(ave_train_img);
	free(std_train_img);
	for(int i=0; i<r_test_img; i++)
		free(d_test_img[i]);
	//free text feature memory
	for(int i=0; i<c_train_txt; i++)
		free(d_train_txt_t[i]);
	free(ave_train_txt);
	free(std_train_txt);
	for(int i=0; i<r_test_txt; i++)
		free(d_test_txt[i]);
	return;
}

//get the dimension of the input matrix
bool CChildFrame::GetDataDimension(char* f_input, int f_len, int* d_column, int* d_row)
{
//create a temporal char* for storing the converted char*
	char d_convert[50];
//convert the number of columns
	//search for the beginning and ending of the converted chars
	int d_start=0;
	int d_end = bf.SearchForward(';', f_input, d_start, f_len);
	//if legal end found, assgin the chars to d_convert for converting
	if(d_end<f_len)
	{
		for(int i=0; i<(d_end-d_start); i++)
			d_convert[i] = f_input[d_start+i];
		d_convert[d_end-d_start] = NULL;
	//convert the char
		*d_column = (int)atof(d_convert);
	}
	else
		return 0;
//convert the number of rows
	d_start = d_end+1;
	d_end = bf.SearchForward(';', f_input, d_start, f_len);
	//legal end found, assign the chars for converting
	if(d_end<f_len)
	{
		for(int i=0; i<(d_end-d_start); i++)
			d_convert[i] = f_input[d_start+i];
		//inseart end after the last char
		d_convert[d_end-d_start] = NULL;
		//conver the char
		*d_row = (int)atof(d_convert);
	}
	else
		return 0;
	return 1;
}

//read the data into the matrix
bool CChildFrame::ReadMatrixData(char* f_input, int f_len, int d_column, int d_row, double** m_data)
{
	//define a char for converting
	char d_convert[50];
	//search forward to the start of matrix data
	int d_start = bf.SearchForward('\n', f_input, 0, f_len);
	d_start ++;
	//validate the location of d_start
	if(d_start>=f_len)
	{
		::AfxMessageBox(CString("File length not correct, Please check!"), MB_OK, 0);
		return 0;
	}
	//start to read data;
	int d_end;
	int count = 0;	//count the number of data read
	int cur_column = 0;
	int cur_row = 0;
	//loop to load the data until d_start reach the end
	while(d_start<f_len)
	{
		//search for the end of data
		d_end = bf.SearchForward(';', f_input, d_start, f_len);
		//validate and load the chars to be converted
		if(d_end<f_len)
		{
			if(d_end-d_start<50)
			{
				for(int i=0; i<(d_end-d_start); i++)
					d_convert[i] = f_input[d_start+i];
				d_convert[d_end-d_start] = NULL;
				//convert the chars to double and increase the current position by 1
				m_data[cur_row][cur_column] = atof(d_convert);
				cur_column ++;
				//if current column reach the limit, restart from 0 and increase the row by 1
				if(cur_column >= d_column)
				{
					cur_column = 0;
					cur_row ++;
				}
				count ++;
			}
			else
			{
				CString error("Error!!\r\nPlease check data at location: (");
				error += bf.douTostr(cur_row);
				error += CString(", ");
				error += bf.douTostr(cur_column);
				error += CString(").");
				::AfxMessageBox(error, MB_OK, 0);
				return 0;
			}
		}	
		d_start = d_end+1;
	}
	//validate the number of data read
	if(count != d_column*d_row)
	{
		CString error("Error!!\r\nNumber of data indicate are: ");
		error += bf.douTostr(d_column*d_row);
		error += CString("\r\nNumber of data read are: ");
		error += bf.douTostr(count);
		::AfxMessageBox(error, MB_OK, 0);
		return 0;
	}
	return 1;
}

//get the linguistic features from the files in a folder
void CChildFrame::GetFolderLinguistic(void)
{
//set corpus
	if(!is_corpus_set)
	{
		::AfxMessageBox(CString("Corpus not set!!\r\nPlease select a file containing the corpus"), MB_OK, 0);
		CChildFrame::SetCorpus();
	}
	//if failed to set corpus
	if(!is_corpus_set)
	{
		::AfxMessageBox(CString("Failed to set corpus"), MB_OK, 0);
		return;
	}
//define a folderview
	LPWSTR lpszDir = new WCHAR[_MAX_PATH];
	LPWSTR buffer = new WCHAR[_MAX_PATH];

	::OleInitialize(NULL);
	BROWSEINFO br_info;
	memset(&br_info, 0, sizeof(br_info));
//browse the path for images
	br_info.ulFlags = BIF_USENEWUI;
	br_info.hwndOwner = NULL;
	br_info.lpszTitle = _T("Please Select a Folder for Text Files");

	LPITEMIDLIST pidl;
	pidl = ::SHBrowseForFolder(&br_info);

	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDir) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	else
	{
		::AfxMessageBox(CString("No folder selected"), MB_OK, 0);
		return;
	}
	::OleUninitialize();
//*end of browse for images
	CString findfile = lpszDir;
	COutput outdata;
	outdata.m_string = CString("Please replace this with what you are searching for: Caption/Reference");
	outdata.DoModal();
	findfile += "\\*";
	findfile += outdata.m_string;
	findfile += ".txt";
	CFileFind finder;
	BOOL bWorking = finder.FindFile(findfile);
	CString str;
	int count = 0;
	while (bWorking)
	{
		//find the next file
		bWorking = finder.FindNextFile();
		//combine the file path
		LPTSTR filename = ::PathCombineW(buffer, lpszDir, finder.GetFileName());
		//get the linguistic feature from the file
		double* l_feature = CChildFrame::getLinguisticFeature(CString(filename));
		//write it to the string
		for(int i=0; i<num_division; i++)
		{
			str += bf.douTostr(l_feature[i]);
			str += CString(";");
		}
		str += CString("\r\n");
		//free the memory
		free(l_feature);
		count ++;
	}
	//get the dimension of the matrix
	CString datamatrix = bf.douTostr(num_division);
	datamatrix += CString(";");
	datamatrix += bf.douTostr(count);
	datamatrix += CString("\r\n");
	//combine the string
	datamatrix += str;
	//write the matrix to file
	bf.stringToFile(datamatrix, CString("Save the linguistic feature as ..."));
	
	return;
}

//Generate a matrix with random double numbers
void CChildFrame::OnGenerateMatrix(void)
{
	//assign the columns and rows of the matrix
	COutput outdata;
	outdata.m_data1 = 10;
	outdata.m_data2 = 10;
	outdata.m_string = CString("MatrixColumn\tMatrixRow");
	outdata.DoModal();
	//generate the matrix
	double** randomMatrix = bf.RandomDoubleMatrix((int)outdata.m_data1, (int)outdata.m_data2);
	CString str;
	//write the dimension of the matrix
	str += bf.douTostr(outdata.m_data1);
	str += ";";
	str += bf.douTostr(outdata.m_data2);
	str += ";\r\n";
	//write the content of the matrix
	for(int i=0; i<(int)outdata.m_data2; i++)
	{
		for(int j=0; j<(int)outdata.m_data1; j++)
		{
			str += bf.douTostr(randomMatrix[i][j]);
			str += ";";
		}
		str += "\r\n";
	}
	//write the matrix to file
	bf.stringToFile(str, CString("Save the Random Matrix as ..."));
	return;
}

//load images with captions, reference, etc into the database
void CChildFrame::OnLoadDatabase(void)
{
	//specify the training image or testing image, cutted images or whole panel iamges
	BOOL isTraining = TRUE;
	BOOL isCutted = TRUE;
	int isTrained = ::AfxMessageBox(CString("Are you going to load training data?\r\nYes: Load Training Images\r\nNo: Load Testing Images"), MB_YESNO, 0);
	if(isTrained == IDNO)
		isTraining = FALSE;
	int isCutting = ::AfxMessageBox(CString("Are you going to load cutted images?\r\nYes: Cutted Images\r\nNo: Whole Panel"), MB_YESNO, 0);
	if(isCutting == IDNO)
		isCutted = FALSE;
	LPWSTR lpszDir = new WCHAR[_MAX_PATH];
	LPWSTR buffer = new WCHAR[_MAX_PATH];

	::OleInitialize(NULL);
	BROWSEINFO br_info;
	memset(&br_info, 0, sizeof(br_info));
//browse the path for images
	br_info.ulFlags = BIF_USENEWUI;
	br_info.hwndOwner = NULL;
	br_info.lpszTitle = _T("Please Select a Folder for Images");

	LPITEMIDLIST pidl;
	pidl = ::SHBrowseForFolder(&br_info);

	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDir) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	else
	{
		::AfxMessageBox(CString("No folder selected"), MB_OK, 0);
		return;
	}
	::OleUninitialize();
//*end of browse for images
	CString findfile = lpszDir;
	findfile += "\\*.bmp";
	CFileFind finder;
	BOOL bWorking = finder.FindFile(findfile);
	int count = 0;
	CString str;
//database recordset
	CImageData imageindex;
	//open the database
	imageindex.Open();
	while (bWorking)
	{
		imageindex.AddNew();
		//read the next file
		bWorking = finder.FindNextFile();

		//combine the file name and read it
		LPTSTR filename = ::PathCombine(buffer, lpszDir, finder.GetFileName());
		CFile cfile;
		CFileStatus filestatus;
		CFileException e;
		//open the file
		if(!cfile.Open(filename, CFile::modeRead, &e))
		{
			::AfxMessageBox(CString("Failed to open file:\r\n")+CString(filename), MB_OK, 0);
			return;
		}

		//locate a global memroy for reading the file
		HGLOBAL hGlobal = GlobalAlloc(GPTR, (SIZE_T)cfile.GetLength());
		//lock the dataset to the memory
		imageindex.m_ImageContent.m_hData = GlobalLock(hGlobal);
		try
		{
			UINT nByteRead = cfile.Read(imageindex.m_ImageContent.m_hData, (UINT)cfile.GetLength());
			imageindex.m_ImageContent.m_dwDataLength = (UINT)cfile.GetLength();
		}
		catch(CException *e)	//catch the errors and display it
		{
			e->ReportError();
			return;
		}

		cfile.Close();
		imageindex.SetFieldDirty(&imageindex.m_ImageContent, 1);
		imageindex.SetFieldNull(&imageindex.m_ImageContent, 0);

		//assign the file name to the database
		imageindex.m_ImageName = CStringA(finder.GetFileName());
		
		//open the caption file and the reference file to load data
		//build file names
		CString captionfile = CString(filename);
		CString referencefile = CString(filename);
		captionfile.Truncate(captionfile.GetLength()-4);
		referencefile.Truncate(referencefile.GetLength()-4);
		captionfile += CString("_Caption.txt");
		referencefile += CString("_Reference.txt");
		//read caption
		if(!cfile.Open(captionfile, CFile::modeRead, &e))
		{
			::AfxMessageBox(CString("Failed to load caption:\r\n")+captionfile, MB_OK, 0);
			return;
		}
		char* caption = (char*)malloc(sizeof(char)*(int)cfile.GetLength());
		UINT nByteRead = cfile.Read(caption, (UINT)cfile.GetLength());
		imageindex.m_Caption = CStringA(caption, (int)cfile.GetLength());
		cfile.Close();
		//read reference
		if(!cfile.Open(referencefile, CFile::modeRead, &e))
		{
			::AfxMessageBox(CString("Failed to load reference:\r\n")+referencefile, MB_OK, 0);
			return;
		}
		char* reference = (char*)malloc(sizeof(char)*(int)cfile.GetLength());
		nByteRead = cfile.Read(reference, (UINT)cfile.GetLength());
		imageindex.m_Reference = CStringA(reference, (int)cfile.GetLength());
		cfile.Close();
		//get the year of the publication
		CString yearchar = finder.GetFileName();
		yearchar.Truncate(4);
		char* publicationyear = bf.CStringToChar(yearchar);
		imageindex.m_Year = atoi(publicationyear);

		//specified the status of the image
		imageindex.m_IsCutted = isCutted;
		imageindex.m_IsTraining = isTraining;

		//update the dataset
		try
		{
			imageindex.Update();
		}
		catch(CException *e) //catch the errors and display it
		{
			e->ReportError();
			return;
		}
		//free the memory
		free(caption);
		free(reference);
		GlobalUnlock(hGlobal);
		GlobalDiscard(hGlobal);
	}
	imageindex.Close();
	//close the database
	return;	
}

//pop-up the image retrieval dialog
void CChildFrame::OnImageRetrieval(void)
{
	//validate if the dialog is already created or not
	if(m_ImageRetrieval==NULL)
	{
		m_ImageRetrieval = new CImageRetrieval(this);
		//create the dialog
		if(m_ImageRetrieval->Create()==FALSE)
		{
			::AfxMessageBox(CString("Failed to Create the Dialog!"), MB_OK, 0);
			return;
		}
		//show the dialog
		m_ImageRetrieval->ShowWindow(SW_SHOW);
	}
	else
		m_ImageRetrieval->ShowWindow(SW_SHOW);
	return;
}

//load the fulltext of the images to the database
void CChildFrame::OnLoadFulltext(void)
{
	//browser a folder containing the full text
	LPWSTR lpszDir = new WCHAR[_MAX_PATH];
	LPWSTR buffer = new WCHAR[_MAX_PATH];

	::OleInitialize(NULL);
	BROWSEINFO br_info;
	memset(&br_info, 0, sizeof(br_info));
//browse the path for images
	br_info.ulFlags = BIF_USENEWUI;
	br_info.hwndOwner = NULL;
	br_info.lpszTitle = _T("Please Select a Folder for the Fulltext");

	LPITEMIDLIST pidl;
	pidl = ::SHBrowseForFolder(&br_info);

	if(pidl != NULL)
	{
		// Create a buffer to store the path, then 
		// get the path.
		if(::SHGetPathFromIDList(pidl, lpszDir) != 0)
		{
			// Set the string value.
		}
		// free the item id list
		CoTaskMemFree(pidl);
	}
	else
	{
		::AfxMessageBox(CString("No folder selected"), MB_OK, 0);
		return;
	}
	::OleUninitialize();

	//open the database
	CImageData m_ImageIndex;
	m_ImageIndex.Open();
	//loop the database and open recordset
	while(!m_ImageIndex.IsEOF())
	{
		m_ImageIndex.Edit();
		//get the filename
		char* m_ImageName = m_ImageIndex.m_ImageName.GetBuffer();
		int m_NameLen = m_ImageIndex.m_ImageName.GetLength();
		//retrieve the fulltext file name
		int m_FulltextLen = bf.SearchForward('_', m_ImageName, 0, m_NameLen);
		m_FulltextLen = bf.SearchForward('_', m_ImageName, m_FulltextLen, m_NameLen);
		m_FulltextLen = bf.SearchForward('_', m_ImageName, m_FulltextLen, m_NameLen);
		m_FulltextLen = bf.SearchForward('_', m_ImageName, m_FulltextLen, m_NameLen);
		CString m_FulltextName = CString(m_ImageName, m_FulltextLen);
		m_FulltextName += CString(".txt");
		//combine the path
		LPTSTR m_FulltextPath = ::PathCombine(buffer, lpszDir, m_FulltextName);
		//open the fulltext file
		CFile cfile;
		CFileException e;
		if(!cfile.Open(m_FulltextPath, CFile::modeRead, &e))	//if failed to open the fulltext
		{
			//write the message to log
			WCHAR ErrorMsg[1024];
			e.GetErrorMessage(ErrorMsg, 1024, 0);
			bf.WriteToLog(CString(ErrorMsg));
		}
		else
		{
			//read the file
			char* m_FileContent = (char*)malloc(sizeof(char)*(int)cfile.GetLength());
			UINT nByteRead = cfile.Read(m_FileContent, (UINT)cfile.GetLength());
			int m_LeftOver = (int)nByteRead;
			//partition into three section and load to log
			//write the first part
			if(m_LeftOver>SHRT_MAX)
			{
				m_ImageIndex.m_Fulltext1 = CStringA(m_FileContent, SHRT_MAX);
				m_LeftOver -= SHRT_MAX;
			}
			else if(m_LeftOver>0)
			{
				m_ImageIndex.m_Fulltext1 = CStringA(m_FileContent, m_LeftOver);
				m_LeftOver -= SHRT_MAX;
			}
			//write the second part
			if(m_LeftOver>SHRT_MAX)
			{
				m_ImageIndex.m_Fulltext2 = CStringA(&m_FileContent[SHRT_MAX], SHRT_MAX);
				m_LeftOver -= SHRT_MAX;
			}
			else if(m_LeftOver>0)
			{
				m_ImageIndex.m_Fulltext2 = CStringA(&m_FileContent[SHRT_MAX], m_LeftOver);
				m_LeftOver -= SHRT_MAX;
			}
			//write the third part
			if(m_LeftOver>SHRT_MAX)
			{
				m_ImageIndex.m_Fulltext3 = CStringA(&m_FileContent[SHRT_MAX*2], SHRT_MAX);
				m_LeftOver -= SHRT_MAX;
			}
			else if(m_LeftOver>0)
			{
				m_ImageIndex.m_Fulltext3 = CStringA(&m_FileContent[SHRT_MAX*2], m_LeftOver);
				m_LeftOver -= SHRT_MAX;
			}
			//write the forth part
			if(m_LeftOver>SHRT_MAX)
			{
				m_ImageIndex.m_Fulltext4 = CStringA(&m_FileContent[SHRT_MAX*3], SHRT_MAX);
				m_LeftOver -= SHRT_MAX;
				CString ErrorMsg("Fulltext content of image (");
				ErrorMsg += CString(m_ImageIndex.m_ImageName);
				ErrorMsg += CString(") exceed ");
				ErrorMsg += bf.douTostr(m_LeftOver);
				ErrorMsg += CString(" characters");
				bf.WriteToLog(ErrorMsg);
			}
			else if(m_LeftOver>0)
			{
				m_ImageIndex.m_Fulltext4 = CStringA(&m_FileContent[SHRT_MAX*3], m_LeftOver);
				m_LeftOver -= SHRT_MAX;
			}
			//set the field dirty
			m_ImageIndex.SetFieldDirty(&m_ImageIndex.m_Fulltext1, 1);
			m_ImageIndex.SetFieldDirty(&m_ImageIndex.m_Fulltext2, 1);
			m_ImageIndex.SetFieldDirty(&m_ImageIndex.m_Fulltext3, 1);
			//update the database
			m_ImageIndex.Update();
		}
		m_ImageIndex.MoveNext();
	}
	m_ImageIndex.Close();
}

//update the pane
void CChildFrame::OnUpdatePane(CCmdUI *pCmdUI)
{
	CChildFrame::GetWindowRect(&m_ChildFrameSize);
	m_wndStatusBar.SetPaneInfo(m_wndStatusBar.CommandToIndex(ID_PIXEL_INFO), ID_PIXEL_INFO, SBPS_POPOUT, m_ChildFrameSize.right);
	m_wndStatusBar.SetPaneText(m_wndStatusBar.CommandToIndex(ID_PIXEL_INFO), CString(m_ColourInfo), 1);
	return;
}

//update the colour information
void CChildFrame::UpdateColourInfo(CStringA str)
{
	m_ColourInfo = str;
}

//save the cross modal to database
void CChildFrame::OnSaveCrossModal(void)
{
	//open the database and delete all records
	CCrossModal m_CrossModal;
	try
	{
		m_CrossModal.Open();
	}
	catch(CException *e)
	{
		e->ReportError();
		return;
	}
	//count the number of records
	int m_RecordCount = 0;
	while(!m_CrossModal.IsEOF())
	{
		m_RecordCount ++;
		m_CrossModal.MoveNext();
	}
	//move back to the first
	m_CrossModal.MoveFirst();
	if(m_RecordCount==1)
		m_CrossModal.Delete();
	if(m_RecordCount>1)
	{
		while(!m_CrossModal.IsEOF())
		{
			try
			{
				m_CrossModal.Delete();
				m_CrossModal.MoveNext();
			}
			catch(CDBException* e)
			{
				e->ReportError();
				return;
			}
		}
	}
	//save the cross modal linke to the database
	//get the data of the SOM
	double** m_SOM1 = m_CrossNet->NetGetSOM1Lattice();
	double** m_SOM2 = m_CrossNet->NetGetSOM2Lattice();
	double** m_Hebbian = m_CrossNet->NetGetHebbian();
	int m_SizeX1;
	int m_SizeX2;
	int m_SizeY1;
	int m_SizeY2;
	int m_DataDimension1;
	int m_DataDimension2;
	m_CrossNet->NetGetDimension(&m_SizeX1, &m_SizeY1, &m_SizeX2, &m_SizeY2, &m_DataDimension1, &m_DataDimension2);
	//save the data to the database
	//save the first link as the size of the data
	double* m_SizeSOM1 = new double[3];
	double* m_SizeSOM2 = new double[3];
	double* m_SizeHebbian = new double[2];
	m_SizeSOM1[0] = m_SizeX1;
	m_SizeSOM1[1] = m_SizeY1;
	m_SizeSOM1[2] = m_DataDimension1;
	m_SizeSOM2[0] = m_SizeX2;
	m_SizeSOM2[1] = m_SizeY2;
	m_SizeSOM2[2] = m_DataDimension2;
	m_SizeHebbian[0] = m_SizeX1*m_SizeY1;
	m_SizeHebbian[1] = m_SizeX2*m_SizeY2;
	//convert the size to string for database
	int m_CharSizeSOM1;
	int m_CharSizeSOM2;
	int m_CharSizeHebbian;
	char* m_CharSOM1 = bf.DoubleVectorToChar(m_SizeSOM1, 3, 5, ';', &m_CharSizeSOM1);
	char* m_CharSOM2 = bf.DoubleVectorToChar(m_SizeSOM2, 3, 5, ';', &m_CharSizeSOM2);
	char* m_CharHebbian = bf.DoubleVectorToChar(m_SizeHebbian, 2, 6, ';', &m_CharSizeHebbian);
	//save the size of the map to the database
	m_CrossModal.AddNew();
	m_CrossModal.m_SOM1 = CStringA(m_CharSOM1, m_CharSizeSOM1);
	m_CrossModal.m_SOM2 = CStringA(m_CharSOM2, m_CharSizeSOM2);
	m_CrossModal.m_HebbianLink = CStringA(m_CharHebbian, m_CharSizeHebbian);
	m_CrossModal.Update();
	//save the first SOM and hebbian link to the database
	for(int i=0; i<m_SizeX1; i++)
	{
		for(int j=0; j<m_SizeY1; j++)
		{
			m_CrossModal.AddNew();
			m_CharSOM1 = bf.DoubleVectorToChar(m_SOM1[i*m_SizeX1+j], m_DataDimension1, 10, ';', &m_CharSizeSOM1);
			m_CharHebbian = bf.DoubleVectorToChar(m_Hebbian[i*m_SizeX1+j], m_SizeX1*m_SizeY1, 10, ';', &m_CharSizeHebbian);
			m_CrossModal.m_SOM1 = CStringA(m_CharSOM1, m_CharSizeSOM1);
			m_CrossModal.m_HebbianLink = CString(m_CharHebbian, m_CharSizeHebbian);
			m_CrossModal.Update();
		}
	}
	//save the second SOM to the database
	//move the database pointer to the second of the database
	m_CrossModal.Requery();
	m_CrossModal.MoveNext();
	bool m_EndFlag = 1;
	for(int i=0; i<m_SizeX2; i++)
	{
		for(int j=0; j<m_SizeY2; j++)
		{
			if(m_EndFlag)
			{
				m_CrossModal.Edit();
				m_CharSOM2 = bf.DoubleVectorToChar(m_SOM2[i*m_SizeX2+j], m_DataDimension2, 10, ';', &m_CharSizeSOM2);
				m_CrossModal.m_SOM2 = CStringA(m_CharSOM2, m_CharSizeSOM2);
				m_CrossModal.SetFieldDirty(&m_CrossModal.m_SOM2);
				m_CrossModal.Update();
				m_CrossModal.MoveNext();
				if(m_CrossModal.IsEOF())
					m_EndFlag = 0;
			}
			else
			{
				m_CrossModal.AddNew();
				m_CharSOM2 = bf.DoubleVectorToChar(m_SOM2[i*m_SizeX2+j], m_DataDimension2, 10, ';', &m_CharSizeSOM2);
				m_CrossModal.m_SOM2 = CStringA(m_CharSOM2, m_CharSizeSOM2);
				m_CrossModal.Update();
			}
		}
	}
	//close the database
	m_CrossModal.Close();
	return;
}

//load the cross modal from database
void CChildFrame::OnLoadCrossModal(void)
{
	//open the database
	CCrossModal m_CrossModal;
	try
	{
		m_CrossModal.Open();
	}
	catch(CException *e)
	{
		e->ReportError();
		return;
	}
	m_CrossModal.MoveFirst();
	//load the size of the maps
	int m_SizeX1;
	int m_SizeX2;
	int m_SizeY1;
	int m_SizeY2;
	int m_DataDimension1;
	int m_DataDimension2;
	//load the cross modal
	//load size of the SOM and hebbian links
	int m_SizeSOM1Num;
	int m_SizeSOM2Num;
	int m_SizeHebbianNum;
	double* m_SizeSOM1 = bf.CharToDoubleVector(m_CrossModal.m_SOM1.GetBuffer(), m_CrossModal.m_SOM1.GetLength(),
		';', &m_SizeSOM1Num);
	double* m_SizeSOM2 = bf.CharToDoubleVector(m_CrossModal.m_SOM2.GetBuffer(), m_CrossModal.m_SOM2.GetLength(),
		';', &m_SizeSOM2Num);
	//validate the number of size double read
	if(m_SizeSOM1Num!=3)
	{
		::AfxMessageBox(CString("Size of SOM1 error!"), MB_OK, 0);
		return;
	}
	if(m_SizeSOM2Num!=3)
	{
		::AfxMessageBox(CString("Size of SOM2 error!"), MB_OK, 0);
		return;
	}
	//load the size
	m_SizeX1 = (int)m_SizeSOM1[0];
	m_SizeY1 = (int)m_SizeSOM1[1];
	m_DataDimension1 = (int)m_SizeSOM1[2];
	m_SizeX2 = (int)m_SizeSOM2[0];
	m_SizeY2 = (int)m_SizeSOM2[1];
	m_DataDimension2 = (int)m_SizeSOM2[2];
	//load main datas
	//create memory
	double** m_DataSOM1 = (double**)malloc(sizeof(double*)*m_SizeX1*m_SizeY1);
	double** m_DataSOM2 = (double**)malloc(sizeof(double*)*m_SizeX2*m_SizeY2);
	double** m_DataHebbian = (double**)malloc(sizeof(double*)*m_SizeX1*m_SizeY1);
	//loop to load data
	//load SOM1 and hebbian links
	for(int i=0; i<m_SizeX1*m_SizeY1; i++)
	{
		//validate if the end of record
		if(m_CrossModal.IsEOF())
		{
			::AfxMessageBox(CString("Cross modal database error!"), MB_OK, 0);
			return;
		}
		//move to the next record
		m_CrossModal.MoveNext();
		//load the first SOM
		m_DataSOM1[i] = bf.CharToDoubleVector(m_CrossModal.m_SOM1.GetBuffer(), m_CrossModal.m_SOM1.GetLength(),
			';', &m_SizeSOM1Num);
		//load the hebbian links
		m_DataHebbian[i] = bf.CharToDoubleVector(m_CrossModal.m_HebbianLink.GetBuffer(), m_CrossModal.m_HebbianLink.GetLength(),
			';', &m_SizeHebbianNum);
		//validate the first SOM
		if(m_SizeSOM1Num!=m_DataDimension1)
		{
			::AfxMessageBox(CString("Data dimension of first SOM in database error at line: ")+bf.douTostr(i), MB_OK, 0);
			return;
		}
		//validate the hebbian links
		if(m_SizeHebbianNum!=m_SizeX1*m_SizeY1)
		{
			::AfxMessageBox(CString("Data dimension of Hebbian links in databse error at line: ")+bf.douTostr(i), MB_OK, 0);
			return;
		}
	}
	//load the SOM2
	m_CrossModal.MoveFirst();
	m_CrossModal.MoveNext();
	for(int i=0; i<m_SizeX2*m_SizeY2; i++)
	{
		//validate if the end of record
		if(m_CrossModal.IsEOF())
		{
			::AfxMessageBox(CString("Cross modal database error!"), MB_OK, 0);
			return;
		}
		//move to the next records;
		m_DataSOM2[i] = bf.CharToDoubleVector(m_CrossModal.m_SOM2.GetBuffer(), m_CrossModal.m_SOM2.GetLength(),
			';', &m_SizeSOM2Num);
		//validate the second SOM
		if(m_SizeSOM2Num!=m_DataDimension2)
		{
			::AfxMessageBox(CString("Data dimension of second SOM in database error at line: ")+bf.douTostr(i), MB_OK, 0);
			return;
		}
	}
	//close the databse
	m_CrossModal.Close();
	//load the cross modal
	if(m_CrossNet==NULL)
		m_CrossNet = new CCrossNet(m_SizeX1, m_SizeY1, m_DataDimension1, m_SizeX2, m_SizeY2, m_DataDimension2, 1000);
	m_CrossNet->NetLoadFromMatrix(m_DataSOM1, m_DataSOM2, m_DataHebbian, m_SizeX1, m_SizeY1, m_DataDimension1, m_SizeX2, m_SizeY2, m_DataDimension2);
	return;
}

//Manual annotation dialog
void CChildFrame::ManualAnnotation(void)
{
//Construct the annotation view
	if(m_ManualAnnotation==NULL)	//if the dialog have not been created
	{
		m_ManualAnnotation = new CAnnotationTool(this);
		if(m_ManualAnnotation->Create()==FALSE)
		{
			::AfxMessageBox(CString("Failed to create the dialog!"), MB_OK, 0);
			return;
		}
		//show the dialog
		m_ManualAnnotation->ShowWindow(SW_SHOW);
	}
	else
		m_ManualAnnotation->ShowWindow(SW_SHOW);
	return;
}

//Get the list of words from a set of files
void CChildFrame::GetListOfWords(void)
{
	CString strFilter = CString("text file (*.txt)|*.txt||");
	//Pop up a dialog to select the files
	CFileDialog filedialog(TRUE, NULL, NULL, OFN_FILEMUSTEXIST|OFN_ALLOWMULTISELECT, strFilter);
	//Display the dialog to load text files
	TCHAR* filestructure = new TCHAR[2048*10];
	filedialog.m_ofn.lpstrFile = filestructure;
	filestructure[0] = '\0';
	filedialog.m_ofn.nMaxFile = 2048*10;
	HRESULT m_hResult = (int)filedialog.DoModal();

	//Get the string in each file and merge them to allfilestring
	string allfilestring;
	POSITION fileposition = filedialog.GetStartPosition();
	int filecount = 0;
	while(fileposition!=NULL)
	{
		//Get the next file and load it into allfilestring
		CFile cfile;
		try
		{	//Open the file, load into char, store it into the string
			cfile.Open(filedialog.GetNextPathName(fileposition), CFile::modeRead);
			char* filechar = new char[(size_t)cfile.GetLength()];
			cfile.Read(filechar, (UINT)cfile.GetLength());
			allfilestring += string(filechar, (UINT)cfile.GetLength());
			cfile.Close();
			delete (filechar);
		}
		catch(CFileException* e)
		{
			e->ReportError();
		}
		filecount ++;
	}
	delete filestructure;
	string lowercasestring = bf.ChangeToLowerCase(allfilestring);
	vector<unsigned int> frequency;
	vector<string> wordlist = bf.LoadWordsFromString(allfilestring, frequency);
	vector<double> weirdness = bf.ComputerWeirdness(wordlist, frequency);

	////Output the results
	std::ostringstream systemstring;
	for(unsigned int i=0; i<wordlist.size(); i++)
		systemstring << wordlist[i] << '\t' << frequency[i] << '\t' << weirdness[i] << "\r\n";

	bf.stringToFile(CString(systemstring.str().c_str()), CString("Save the results as ..."));

	return;
}

//Do the collocations for a set of words
void CChildFrame::Collocations(void)
{
	CString strFilter = CString("text file (*.txt)|*.txt||");
	//Pop up a dialog to select the files
	CFileDialog filedialog(TRUE, NULL, NULL, OFN_FILEMUSTEXIST|OFN_ALLOWMULTISELECT, strFilter);
	//Display the dialog to load text files
	TCHAR* filestructure = new TCHAR[2048*10];
	filedialog.m_ofn.lpstrFile = filestructure;
	filestructure[0] = '\0';
	filedialog.m_ofn.nMaxFile = 2048*10;
	CString dialogtitle("Open files for collocations ...");
	filedialog.m_ofn.lpstrTitle = dialogtitle;
	HRESULT m_hResult = (int)filedialog.DoModal();

	//Get the string in each file and merge them to allfilestring
	string allfilestring;
	POSITION fileposition = filedialog.GetStartPosition();
	int filecount = 0;
	while(fileposition!=NULL)
	{
		//Get the next file and load it into allfilestring
		CFile cfile;
		try
		{	//Open the file, load into char, store it into the string
			cfile.Open(filedialog.GetNextPathName(fileposition), CFile::modeRead);
			char* filechar = new char[(size_t)cfile.GetLength()];
			cfile.Read(filechar, (UINT)cfile.GetLength());
			allfilestring += string(filechar, (UINT)cfile.GetLength());
			cfile.Close();
			delete (filechar);
		}
		catch(CFileException* e)
		{
			e->ReportError();
		}
		filecount ++;
	}
	delete filestructure;
	string lowercasestring = bf.ChangeToLowerCase(allfilestring);

	//Get a list of terms for collocations
	CTermInput terminput;
	terminput.DoModal();

	bf.WriteToFile(CString("C:\\temp.txt"), terminput.m_terms);
	vector<string> keywords = bf.LoadWordsFromString("c:\\temp.txt");
	////Get the term list
	//vector<string> termlist;
	//vector<unsigned int> frequency;
	//termlist = bf.LoadWordsFromString(lowercasestring, frequency);
	//vector<double> weirdness = bf.ComputerWeirdness(termlist, frequency);

	////Select the important words
	////vector<string> keywords;
	////keywords.push_back("cell");
	//vector<string> keywords = bf.SelectKeyterms(termlist, frequency, weirdness);
	//::AfxMessageBox(bf.douTostr(keywords.size()), MB_OK, 0);

	//Collocations
	vector<vector<double>> collocationfrequency;
	vector<double> collocationsum;
	vector<double> collocationspread;
	vector<string> collocations;
	vector<unsigned int> collocationcounter = bf.Collocations(allfilestring, keywords, collocations,
		collocationfrequency, collocationspread, collocationsum);
	unsigned int wordcounter = 0;

	////Compute the z-score of the collocations for each word frequency and the z-score of the each collocations
	//vector<double> zscoreforword;
	//vector<double> sumoffrequency;
	//vector<vector<double>> zscoreforcollocation;
	//sumoffrequency.resize(keywords.size());
	//for(unsigned int i=0; i<sumoffrequency.size(); i++)
	//	sumoffrequency[i] = 0.0;
	//zscoreforword.resize(collocationspread.size());
	//zscoreforcollocation.resize(zscoreforword.size());
	//unsigned int counter = 0;

	//Output the results
	wordcounter = 0;
	std::ostringstream systemstring;
	for(unsigned int i=0; i<collocations.size(); i++)
	{
		if(i==collocationcounter[wordcounter])
			wordcounter ++;
		systemstring << keywords[wordcounter] << '\t' << collocations[i] << '\t';
		for(unsigned int j=0; j<collocationfrequency[i].size(); j++)
			systemstring << collocationfrequency[i][j] << '\t';
		systemstring << collocationsum[i] << '\t' << collocationspread[i] << "\r\n";
	}
	bf.stringToFile(CString(systemstring.str().c_str()), CString("Save the collocation results as ..."));

	return;
}

//Image clustering
void CChildFrame::ImageClustering(void)
{
//Construct the clustering dialog
	if(imageclustering==NULL)	//if the dialog have not been created
	{
		imageclustering = new CImageClustering(this);
		if(imageclustering->Create()==FALSE)
		{
			::AfxMessageBox(CString("Failed to create the dialog!"), MB_OK, 0);
			return;
		}
		//show the dialog
		imageclustering->ShowWindow(SW_SHOW);
	}
	else
		imageclustering->ShowWindow(SW_SHOW);
	return;
}

void CChildFrame::OnCrossModalDialog()
{
//Construct the clustering dialog
	if(crossmodaldialog==NULL)	//if the dialog have not been created
	{
		crossmodaldialog = new CCrossModalDialog(this);
		if(crossmodaldialog->Create()==FALSE)
		{
			::AfxMessageBox(CString("Failed to create the dialog!"), MB_OK, 0);
			return;
		}
		//show the dialog
		crossmodaldialog->ShowWindow(SW_SHOW);
	}
	else
		crossmodaldialog->ShowWindow(SW_SHOW);
	return;
}

void CChildFrame::BootstrappingMultimodal()
{
	//generate some random numbers of 1, 0
	unsigned int numberofdata = 10000;
	unsigned int numberoftest = 10000;
	double** randomnumber = new double*[2];
	double** testnumber = new double*[numberoftest];
	int* numberpattern = new int[numberofdata];

	double threshold = 10;
	srand((unsigned int)time(NULL));	//seed the random number

	for(unsigned int i=0; i<2; i++)
	{
		randomnumber[i] = new double[numberofdata];
	}

	//generate random numbers based on the defined probability
	for(unsigned int j=0; j<numberofdata/2; j++)
	{
		randomnumber[0][j]=0.0;
		randomnumber[1][j]=0.0;
	}
	for(unsigned int j=numberofdata/2; j<numberofdata; j++)
	{
		//randomnumber[0][j]=0.0;
		//randomnumber[1][j]=0.0;
		int randomnum=rand();
		if(randomnum>=RAND_MAX/2)
		{
			randomnumber[0][j]=0.0;
			randomnumber[1][j]=0.0;
		}
		else if(randomnum>=RAND_MAX/4)
		{
			randomnumber[0][j]=1.0;
			randomnumber[1][j]=0.0;
		}
		else
		{
			randomnumber[0][j]=0.0;
			randomnumber[1][j]=1.0;
		}
	}

	//assigned patterns to each pairs of data
	for(unsigned int j=0; j<numberofdata; j++)
	{
		if(randomnumber[0][j]==1&&randomnumber[1][j]==1)
			numberpattern[j] = 4;
		else if(randomnumber[0][j]==1&&randomnumber[1][j]==0)
			numberpattern[j] = 3;
		else if(randomnumber[0][j]==0&&randomnumber[1][j]==1)
			numberpattern[j] = 2;
		else
			numberpattern[j] = 1;
	}

	//boostrapping?
	int bootstrap = ::AfxMessageBox(_T("use bootstrapping?"), MB_YESNO, 0);
	if(bootstrap==IDYES)
	{
		for(unsigned int i=0; i<numberofdata; i++)
		{
			for(unsigned int j=0; j<2; j++)
			{
				//if the data is equal to 0, bootstrap it
				if(randomnumber[j][i] == 0.0)
				{
					//generate a random number between 0 and 1
					double newnumber = (double)(rand()/2+1)/(double)(rand()/2+1);
					if(newnumber>1)
						newnumber = 1/newnumber;
					//divided by a threshold
					newnumber = newnumber/threshold;
					randomnumber[j][i] = newnumber;
				}
			}
			//if(randomnumber[0][i]>randomnumber[1][i])
			//	numberpattern[i]=1;
			//else
			//	numberpattern[i]=2;
		}
	}

	double minvalue[2] = {0.0, 0.0};
	double maxvalue[2] = {1.0, 1.0};
	COutput sizeofsom;
	sizeofsom.m_string = CString("Please input the size of the SOM");
	sizeofsom.DoModal();
	//CSOM som((int)sizeofsom.m_data1, (int)sizeofsom.m_data2, 2, 1, &(maxvalue[0]), &(minvalue[0]));
	CSOM som((int)sizeofsom.m_data1, (int)sizeofsom.m_data2, 2, 2, &(maxvalue[0]), &(minvalue[0]));
	som.somIllustration(true);
	//som.somTraining(randomnumber, numberofdata, numberpattern);
	som.somTraining(randomnumber, numberofdata/2, numberpattern);
	som.ForceChangeTC(1);
	//copy the other half data out
	double** newdata = new double*[2];
	for(int i=0; i<2; i++)
	{
		newdata[i] = new double[numberofdata-numberofdata/2];
		for(unsigned int j=0; j<numberofdata-numberofdata/2; j++)
			newdata[i][j] = randomnumber[i][numberofdata/2+j];
	}
	som.somTraining(newdata, numberofdata-numberofdata/2, &(numberpattern[numberofdata/2]));

	//generate random number for testing
	for(unsigned int i=0; i<numberoftest; i++)
	{
		testnumber[i] = new double[2];
		double newnumber = (double)rand()/(double)RAND_MAX*(double)0.5;
		testnumber[i][0] = 1-newnumber;
		newnumber =  (double)rand()/(double)RAND_MAX*(double)0.5;
		testnumber[i][1] = 1-newnumber;
	}
	//save the data
	//int num;
	//char* datachar = bf.DoubleMatrixToChar(testnumber, numberoftest, 2, 10, '\t', &num);
	//bf.WriteToFile(CString("c:\\testdata.txt"), CString(datachar, num));
	rgb testcolour = {0, 0, 255};
	for(unsigned int i=0; i<numberoftest; i++)
		som.getTestingResults(testnumber[i], testcolour);

	//free memory
	delete[] randomnumber[0];
	delete[] randomnumber[1];
	delete[] randomnumber;
	delete[] numberpattern;

	return;
}

void CChildFrame::BootstrappingImages()
{
	int bootstrap = ::AfxMessageBox(_T("bootstrapping?"), MB_YESNO, 0);
	int m=5;
	int n=5;
	int imagefeaturesize = m_wndView.getZernikeNum(n, m);
	//if using bootstrapping
	if(bootstrap==IDYES)
	{
		vector<string> firstset;
		vector<string> secondset;
		try
		{
			//pop up dialogs to select a first set of images
			firstset = bf.SelectMultipleFiles(_T("(BITMAP images|*.bmp||"), _T("Select multiple images for the first set"));
			//pop up dialogs to select a second set of images
			secondset = bf.SelectMultipleFiles(_T("(BITMAP images|*.bmp||"), _T("Select multiple images for the second set"));
		}
		catch(string exception)
		{
			::AfxMessageBox(CString(exception.c_str()), MB_OK, 0);
			return;
		}
		//get the features and patterns
		vector<vector<double> > imagefeatures;
		int* patterns = new int[firstset.size()+secondset.size()];
		//for the first set
		for(unsigned int i=0; i<(unsigned int)firstset.size(); i++)
		{
			m_wndView.OnImageOpen(CString(firstset[i].c_str()), _T("temp"));
			double** currentfeature = m_wndView.getZernikeImage(n, m);
			vector<double> feature;
			for(unsigned int j=0; j<(unsigned int)imagefeaturesize*3; j++)
				feature.push_back(sqrt(currentfeature[j][0]*currentfeature[j][0]+currentfeature[j][1]*currentfeature[j][1]));
			imagefeatures.push_back(feature);
			patterns[i] = 1;
		}
		//for the second set
		for(unsigned int i=0; i<(unsigned int)secondset.size(); i++)
		{
			m_wndView.OnImageOpen(CString(secondset[i].c_str()), _T("temp"));
			double** currentfeature = m_wndView.getZernikeImage(n, m);
			vector<double> feature;
			for(unsigned int j=0; j<(unsigned int)imagefeaturesize*3; j++)
				feature.push_back(sqrt(currentfeature[j][0]*currentfeature[j][0]+currentfeature[j][1]*currentfeature[j][1]));
			imagefeatures.push_back(feature);
			patterns[(int)firstset.size()+i] = 2;
		}
		//create  SOM and train it
		int traincycle = 10;
		CSOM som(10, 10, imagefeaturesize*3, traincycle);
		unsigned int dimension1, dimension2;
		double** traindatatranspose = bf.VectorToPointer(imagefeatures, dimension1, dimension2);
		double** traindata = bf.matrixTransp(traindatatranspose, dimension2, dimension1);
		som.somIllustration(1);
		for(unsigned int i=0; i<(unsigned int)traincycle; i++)
		{
			som.somTraining(traindata, dimension1, patterns);
		}
	}
	//if not using bootstrapping
	if(bootstrap==IDNO)
	{
		vector<string> imageset;
		//pop up dialog to select two different image
		try
		{
			imageset = bf.SelectMultipleFiles(_T("(BITMAP image|*.bmp||"), _T("Select two different images"));
		}
		catch(string exception)
		{
			::AfxMessageBox(CString(exception.c_str()), MB_OK, 0);
			return;
		}
		//if not two images are selected
		if(imageset.size()!=2)
		{
			::AfxMessageBox(_T("Please select two images"), MB_OK, 0);
			return;
		}
		//get the features of the two image
		vector<vector<double> > imagefeatures;
		int patterns[2] = {1, 2};
		for(unsigned int i=0; i<(unsigned int)imageset.size(); i++)
		{
			m_wndView.OnImageOpen(CString(imageset[i].c_str()), _T("temp"));
			double** currentfeature = m_wndView.getZernikeImage(n, m);
			vector<double> feature;
			for(unsigned int j=0; j<(unsigned int)imagefeaturesize*3; j++)
				feature.push_back(sqrt(currentfeature[j][0]*currentfeature[j][0]+currentfeature[j][1]*currentfeature[j][1]));
			imagefeatures.push_back(feature);
		}
		//create  SOM and train it
		int traincycle = 1000;
		CSOM som(10, 10, imagefeaturesize*3, traincycle);
		unsigned int dimension1, dimension2;
		double** traindatatranspose = bf.VectorToPointer(imagefeatures, dimension1, dimension2);
		double** traindata = bf.matrixTransp(traindatatranspose, dimension2, dimension1);
		som.somIllustration(1);
		for(unsigned int i=0; i<(unsigned int)traincycle; i++)
		{
			som.somTraining(traindata, dimension1, &(patterns[0]));
		}
	}
	return;
}

//clustering companies
void CChildFrame::ClusteringCompany(void)
{
	//load input
	CFileDialog newdialog(1, 0, 0, 0, _T("txt file(*.txt)|*.txt"), 0, 0);
	newdialog.m_ofn.lpstrTitle = CString("Please select the file containing the company data");
	if(!newdialog.DoModal())
		return;
	CString filepath = newdialog.GetFileName();
	newdialog.m_ofn.lpstrTitle = CString("Please select the file containing the company names");
	if(!newdialog.DoModal())
		return;
	CString namepath = newdialog.GetFileName();
	CT2CA asciistring(namepath);
	string namepatha(asciistring);
	if(filepath.GetLength()<4)
		return;
	CString folderpath(bf.SelectAFolder().c_str());
	if(folderpath.GetLength()<4)
	{
		::AfxMessageBox(CString("no folder selected"), MB_OK, 0);
		return;
	}
	for(unsigned int k=0; k<10; k++){
	//load the company name
	std::ifstream namefile(namepatha.c_str());
	vector<string> companyname;
	while(!namefile.eof())
	{
		string eachline;
		std::getline(namefile, eachline);
		companyname.push_back(eachline);
	}
	int nrow;
	int ncol;

	double** inputdata = bf.LoadDoubleFromFile(filepath, &nrow, &ncol);
	//pick a folder for saving data
	double** temporaltrain = new double*[nrow-10];
	double** temporaltest = new double*[10];
	vector<unsigned int> sequence;
	//normalize input
	double* ave = new double[ncol];
	double* std = new double[ncol];
	//generate a random selected testing set of data
	vector<unsigned int> randomselect(10);
	vector<unsigned int>status(nrow, 0);
	srand((unsigned int)time(NULL));
	unsigned int count=0;
	while(count<10)
	{
		//generate a unsigned int and verify if it is already in the list or not
		unsigned int ran = rand()%100;
		bool flag = true;
		for(unsigned int j=0; j<count; j++)
		{
			if(ran==randomselect[j])
			{
				flag=false;
				continue;
			}
		}
		//if the number not in the list, it is health, else regenerate a new number
		if(flag)
			randomselect[count]=ran;
		else
			continue;
		//set the flag of the select unsigned int to 1
		status[randomselect[count]]=1;
		temporaltest[count]=inputdata[randomselect[count]];
		count++;
	}
	//re arrange the data
	//move the randomly selected data to the last
	vector<string> newnamelist;
	int temporalcount=0;
	for(unsigned int i=0; i<nrow; i++)
		if(status[i]!=1)
		{
			temporaltrain[temporalcount++]=inputdata[i];
			sequence.push_back(i);
			newnamelist.push_back(companyname[i]);
		}
	sequence.insert(sequence.end(), randomselect.begin(), randomselect.end());
	for(unsigned int i=0; i<nrow-10; i++)
		inputdata[i]=temporaltrain[i];
	for(unsigned int i=nrow-10; i<nrow; i++)
	{
		newnamelist.push_back(companyname[randomselect[i-nrow+10]]);
		inputdata[i]=temporaltest[i-nrow+10];
	}
	//write down the data
	int num;
	char* datamatrix = bf.DoubleMatrixToChar(inputdata, nrow, ncol, 5, ';', &num);
	bf.WriteToFile(CString("c:\\data.txt"), CString(datamatrix, num));
	//transpose the data and normalize the data
	double** somdata = bf.matrixTransp(inputdata, ncol, nrow);
	bf.normalizedData(somdata, nrow, ncol, ave, std);
	//train the SOM
	int sizex=10, sizey=10;
	CSOM newsom(sizex, sizey, ncol, 10);
	CSOM newsom2(sizex/2, sizey/2, ncol, 10);
	CSOM newsom3(sizex/4, sizey/4, ncol, 10);
	for(int i=0; i<10; i++)
	{
		newsom.somTraining(somdata, nrow-10);
		double** trainingdata=newsom.getTrainingWinners();
		newsom2.somTraining(trainingdata, nrow-10);
		trainingdata=newsom2.getTrainingWinners();
		newsom3.somTraining(trainingdata, nrow-10);
	}
	int* results = new int[nrow];
	std::ostringstream systemstring;
	std::ostringstream layer2;
	std::ostringstream layer3;
	std::ostringstream names;
	for(int i=0; i<nrow; i++)
	{
		for(int j=0; j<ncol; j++)
			inputdata[i][j] = (inputdata[i][j]-ave[j])/std[j];
		results[i] = newsom.getTestingResults(inputdata[i]);
		systemstring << results[i]/sizex << '\t' << results[i]%sizex << "\r\n";
		int temp = newsom2.getTestingResults(newsom.getTestWinners(inputdata[i]));
		double* tempwinner = newsom2.getTestWinners(newsom.getTestWinners(inputdata[i]));
		layer2 << temp/(sizex/2) << '\t' << temp%(sizex/2) << "\r\n";
		temp = newsom3.getTestingResults(tempwinner);
		layer3 << temp/(sizex/4) << '\t' << temp%(sizex/4) << "\r\n";
		names << newnamelist[i] << "\r\n";
	}

	//pick up a folder to save the data
	bf.WriteToFile(folderpath+CString("\\explayer1round")+(bf.douTostr(k)+CString(".txt")), CString(systemstring.str().c_str()));
	bf.WriteToFile(folderpath+CString("\\explayer2round")+(bf.douTostr(k)+CString(".txt")), CString(layer2.str().c_str()));
	bf.WriteToFile(folderpath+CString("\\explayer3round")+(bf.douTostr(k)+CString(".txt")), CString(layer3.str().c_str()));
	bf.WriteToFile(folderpath+CString("\\nameround")+(bf.douTostr(k)+CString(".txt")), CString(names.str().c_str()));
	delete[] ave;
	delete[] std;
	for(unsigned int i=0; i<nrow; i++)
		delete[] inputdata[i];
	delete[] inputdata;
	delete[] temporaltest;
	delete[] temporaltrain;
	for(unsigned int i=0; i<ncol; i++)
		delete[] somdata[i];
	delete[] results;
	newsom.somDestroy();
	newsom2.somDestroy();
	newsom3.somDestroy();
	}
	return;
}